summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk2
-rw-r--r--api/current.txt591
-rw-r--r--cmds/app_process/Android.mk25
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java34
-rw-r--r--core/java/android/animation/RevealAnimator.java141
-rw-r--r--core/java/android/app/ApplicationPackageManager.java49
-rw-r--r--core/java/android/app/ContextImpl.java9
-rw-r--r--core/java/android/app/INotificationManager.aidl5
-rw-r--r--core/java/android/app/Notification.java118
-rw-r--r--core/java/android/app/PackageInstallObserver.java49
-rw-r--r--core/java/android/app/admin/DeviceAdminInfo.java16
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java2
-rw-r--r--core/java/android/content/Context.java11
-rw-r--r--core/java/android/content/Intent.java13
-rw-r--r--core/java/android/content/pm/IPackageInstallObserver2.aidl45
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl16
-rw-r--r--core/java/android/content/pm/PackageManager.java143
-rw-r--r--core/java/android/content/pm/PackageParser.java4
-rw-r--r--core/java/android/content/res/ColorStateList.java23
-rw-r--r--core/java/android/content/res/TypedArray.java316
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java4
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java7
-rw-r--r--core/java/android/net/http/CertificateChainValidator.java11
-rw-r--r--core/java/android/provider/MediaStore.java4
-rw-r--r--core/java/android/service/notification/INotificationListener.aidl1
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java68
-rw-r--r--core/java/android/service/notification/StatusBarNotification.java19
-rw-r--r--core/java/android/text/DynamicLayout.java17
-rw-r--r--core/java/android/text/Html.java2
-rw-r--r--core/java/android/text/Layout.java12
-rw-r--r--core/java/android/text/MeasuredText.java6
-rw-r--r--core/java/android/text/PackedIntVector.java7
-rw-r--r--core/java/android/text/PackedObjectVector.java15
-rw-r--r--core/java/android/text/SpannableStringBuilder.java53
-rw-r--r--core/java/android/text/SpannableStringInternal.java14
-rw-r--r--core/java/android/text/StaticLayout.java27
-rw-r--r--core/java/android/text/TextLine.java2
-rw-r--r--core/java/android/text/TextUtils.java2
-rw-r--r--core/java/android/util/ArrayMap.java22
-rw-r--r--core/java/android/util/ArraySet.java18
-rw-r--r--core/java/android/util/ContainerHelpers.java4
-rw-r--r--core/java/android/util/LongArray.java8
-rw-r--r--core/java/android/util/LongSparseArray.java57
-rw-r--r--core/java/android/util/LongSparseLongArray.java49
-rw-r--r--core/java/android/util/SparseArray.java57
-rw-r--r--core/java/android/util/SparseBooleanArray.java57
-rw-r--r--core/java/android/util/SparseIntArray.java57
-rw-r--r--core/java/android/util/SparseLongArray.java49
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java2
-rw-r--r--core/java/android/view/View.java16
-rw-r--r--core/java/android/view/ViewRootImpl.java4
-rw-r--r--core/java/android/widget/Editor.java8
-rw-r--r--core/java/android/widget/RemoteViews.java94
-rw-r--r--core/java/android/widget/SearchView.java2
-rw-r--r--core/java/android/widget/SpellChecker.java21
-rw-r--r--core/java/com/android/internal/app/ProcessStats.java22
-rw-r--r--core/java/com/android/internal/util/ArrayUtils.java48
-rw-r--r--core/java/com/android/internal/util/GrowingArrayUtils.java196
-rw-r--r--core/java/com/android/internal/util/ImageUtils.java (renamed from packages/SystemUI/src/com/android/systemui/ImageUtils.java)6
-rw-r--r--core/java/com/android/internal/util/LegacyNotificationUtil.java193
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java1270
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp44
-rw-r--r--core/jni/android/graphics/Canvas.cpp34
-rw-r--r--core/jni/android/graphics/ColorFilter.cpp10
-rw-r--r--core/jni/android/graphics/Graphics.cpp20
-rw-r--r--core/jni/android/graphics/Matrix.cpp63
-rw-r--r--core/jni/android/graphics/Paint.cpp10
-rw-r--r--core/jni/android/graphics/TextLayoutCache.cpp14
-rw-r--r--core/jni/android_net_LocalSocketImpl.cpp6
-rw-r--r--core/jni/android_nio_utils.cpp2
-rw-r--r--core/jni/android_os_Debug.cpp6
-rw-r--r--core/jni/android_server_NetworkManagementSocketTagger.cpp4
-rw-r--r--core/jni/android_text_AndroidBidi.cpp2
-rw-r--r--core/jni/android_text_AndroidCharacter.cpp15
-rw-r--r--core/jni/android_text_format_Time.cpp66
-rw-r--r--core/jni/android_util_Log.cpp2
-rw-r--r--core/jni/android_view_SurfaceControl.cpp46
-rw-r--r--core/res/res/drawable/btn_borderless_quantum.xml6
-rw-r--r--core/res/res/drawable/btn_default_quantum.xml6
-rw-r--r--core/res/res/drawable/notification_icon_legacy_bg.xml (renamed from packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml)0
-rw-r--r--core/res/res/drawable/notification_icon_legacy_bg_inset.xml (renamed from packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml)0
-rw-r--r--core/res/res/drawable/notification_quantum_background.xml2
-rw-r--r--core/res/res/layout/notification_quantum_action.xml2
-rw-r--r--core/res/res/layout/notification_quantum_action_list.xml2
-rw-r--r--core/res/res/layout/notification_quantum_action_tombstone.xml2
-rw-r--r--core/res/res/layout/notification_template_quantum_base.xml2
-rw-r--r--core/res/res/layout/notification_template_quantum_big_base.xml4
-rw-r--r--core/res/res/layout/notification_template_quantum_big_text.xml6
-rw-r--r--core/res/res/layout/notification_template_quantum_inbox.xml6
-rw-r--r--core/res/res/values-am/strings.xml2
-rw-r--r--core/res/res/values/attrs.xml202
-rw-r--r--core/res/res/values/colors.xml3
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/res/res/values/dimens.xml3
-rw-r--r--core/res/res/values/ids.xml1
-rw-r--r--core/res/res/values/public.xml43
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--core/tests/coretests/src/android/content/pm/PackageManagerTests.java10
-rw-r--r--docs/html/design/index.jd1
-rw-r--r--docs/html/develop/index.jd1
-rw-r--r--docs/html/distribute/index.jd1
-rw-r--r--docs/html/index.jd3
-rw-r--r--docs/html/wear/design/index.html609
-rw-r--r--docs/html/wear/design/index.jd173
-rw-r--r--docs/html/wear/design/user-interface.html498
-rw-r--r--docs/html/wear/design/user-interface.jd58
-rw-r--r--docs/html/wear/index.jd (renamed from docs/html/wear/index.html)352
-rw-r--r--docs/html/wear/license.jd (renamed from docs/html/wear/license.html)445
-rw-r--r--docs/html/wear/notifications/creating.html722
-rw-r--r--docs/html/wear/notifications/creating.jd289
-rw-r--r--docs/html/wear/notifications/pages.html500
-rw-r--r--docs/html/wear/notifications/pages.jd61
-rw-r--r--docs/html/wear/notifications/remote-input.html652
-rw-r--r--docs/html/wear/notifications/remote-input.jd213
-rw-r--r--docs/html/wear/notifications/stacks.html512
-rw-r--r--docs/html/wear/notifications/stacks.jd72
-rw-r--r--docs/html/wear/preview/signup.jd (renamed from docs/html/wear/preview/signup.html)446
-rw-r--r--docs/html/wear/preview/start.html693
-rw-r--r--docs/html/wear/preview/start.jd254
-rw-r--r--docs/html/wear/wear_toc.cs74
-rw-r--r--graphics/java/android/graphics/TemporaryBuffer.java2
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/RevealDrawable.java317
-rw-r--r--graphics/java/android/graphics/drawable/Ripple.java257
-rw-r--r--graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java326
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java1955
-rw-r--r--libs/androidfw/BackupData.cpp8
-rw-r--r--libs/androidfw/BackupHelpers.cpp21
-rw-r--r--libs/androidfw/CursorWindow.cpp4
-rw-r--r--libs/androidfw/ResourceTypes.cpp6
-rw-r--r--libs/common_time/common_time_server.cpp2
-rw-r--r--libs/common_time/utils.cpp4
-rw-r--r--libs/hwui/Android.mk1
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp4
-rw-r--r--libs/hwui/DeferredLayerUpdater.h1
-rw-r--r--libs/hwui/DisplayListOp.h18
-rw-r--r--libs/hwui/Layer.cpp13
-rw-r--r--libs/hwui/Layer.h6
-rw-r--r--libs/hwui/OpenGLRenderer.cpp8
-rw-r--r--libs/hwui/OpenGLRenderer.h2
-rw-r--r--libs/hwui/RenderNode.cpp150
-rw-r--r--libs/hwui/RenderNode.h26
-rw-r--r--libs/hwui/ResourceCache.cpp4
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp2
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp143
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h98
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp57
-rw-r--r--libs/hwui/renderthread/RenderProxy.h8
-rw-r--r--libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c12
-rwxr-xr-xmedia/java/android/mtp/MtpDatabase.java9
-rw-r--r--media/tests/omxjpegdecoder/Android.mk1
-rw-r--r--media/tests/omxjpegdecoder/SkOmxPixelRef.cpp46
-rw-r--r--media/tests/omxjpegdecoder/SkOmxPixelRef.h52
-rw-r--r--media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp16
-rw-r--r--media/tests/omxjpegdecoder/omx_jpeg_decoder.h2
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml6
-rw-r--r--packages/SystemUI/res/values-am/strings.xml4
-rw-r--r--packages/SystemUI/res/values-it/strings.xml4
-rw-r--r--packages/SystemUI/res/values/colors.xml2
-rw-r--r--packages/SystemUI/res/values/config.xml4
-rw-r--r--packages/SystemUI/res/values/dimens.xml15
-rw-r--r--packages/SystemUI/src/com/android/systemui/ExpandHelper.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java242
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java142
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java826
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java112
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java399
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java153
-rw-r--r--packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java13
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java3
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityStack.java1
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java155
-rwxr-xr-xservices/core/java/com/android/server/pm/PackageManagerService.java145
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java14
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java12
-rw-r--r--services/core/jni/com_android_server_AlarmManagerService.cpp4
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java128
-rw-r--r--services/java/com/android/server/SystemServer.java8
-rw-r--r--telephony/java/android/telephony/DisconnectCause.java85
-rw-r--r--test-runner/src/android/test/mock/MockPackageManager.java31
-rw-r--r--tests/DynamicDrawableTest/Android.mk26
-rw-r--r--tests/DynamicDrawableTest/AndroidManifest.xml99
-rw-r--r--tests/DynamicDrawableTest/lint.xml3
-rw-r--r--tests/DynamicDrawableTest/res/drawable-hdpi/icon.pngbin0 -> 5141 bytes
-rw-r--r--tests/DynamicDrawableTest/res/drawable/icon.pngbin0 -> 3133 bytes
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml73
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml46
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml137
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml126
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml147
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml76
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml45
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml48
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml41
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml114
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml62
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml90
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml82
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml54
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml48
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml46
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml46
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml45
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml45
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml37
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml29
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml29
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml29
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml33
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml29
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_test01.xml31
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_test02.xml31
-rw-r--r--tests/DynamicDrawableTest/res/values/strings.xml18
-rw-r--r--tests/DynamicDrawableTest/res/values/styles.xml16
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java69
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java89
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java43
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java95
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java36
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java152
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java25
-rw-r--r--tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java8
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java64
-rw-r--r--wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl28
-rw-r--r--wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java48
228 files changed, 10867 insertions, 9230 deletions
diff --git a/Android.mk b/Android.mk
index 33e64d0..58eae8a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -120,6 +120,7 @@ LOCAL_SRC_FILES += \
core/java/android/content/pm/IPackageDataObserver.aidl \
core/java/android/content/pm/IPackageDeleteObserver.aidl \
core/java/android/content/pm/IPackageInstallObserver.aidl \
+ core/java/android/content/pm/IPackageInstallObserver2.aidl \
core/java/android/content/pm/IPackageManager.aidl \
core/java/android/content/pm/IPackageMoveObserver.aidl \
core/java/android/content/pm/IPackageStatsObserver.aidl \
@@ -288,6 +289,7 @@ LOCAL_SRC_FILES += \
telephony/java/com/android/internal/telephony/ISms.aidl \
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
wifi/java/android/net/wifi/IWifiManager.aidl \
+ wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
packages/services/PacProcessor/com/android/net/IProxyService.aidl \
packages/services/Proxy/com/android/net/IProxyCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index b8ae869..e8e8d64 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -287,6 +287,7 @@ package android {
field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
field public static final int angle = 16843168; // 0x10101a0
+ field public static final int animate = 16843822; // 0x101042e
field public static final int animateFirstView = 16843477; // 0x10102d5
field public static final int animateLayoutChanges = 16843506; // 0x10102f2
field public static final int animateOnClick = 16843356; // 0x101025c
@@ -373,18 +374,19 @@ package android {
field public static final int clipChildren = 16842986; // 0x10100ea
field public static final int clipOrientation = 16843274; // 0x101020a
field public static final int clipToPadding = 16842987; // 0x10100eb
+ field public static final int clipToPath = 16843821; // 0x101042d
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int color = 16843173; // 0x10101a5
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
field public static final int colorBackground = 16842801; // 0x1010031
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
- field public static final int colorButtonNormal = 16843781; // 0x1010405
- field public static final int colorButtonNormalColored = 16843783; // 0x1010407
- field public static final int colorButtonPressed = 16843782; // 0x1010406
- field public static final int colorButtonPressedColored = 16843784; // 0x1010408
- field public static final int colorControlActivated = 16843780; // 0x1010404
- field public static final int colorControlNormal = 16843779; // 0x1010403
+ field public static final int colorButtonNormal = 16843828; // 0x1010434
+ field public static final int colorButtonNormalColored = 16843830; // 0x1010436
+ field public static final int colorButtonPressed = 16843829; // 0x1010435
+ field public static final int colorButtonPressedColored = 16843831; // 0x1010437
+ field public static final int colorControlActivated = 16843827; // 0x1010433
+ field public static final int colorControlNormal = 16843826; // 0x1010432
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -405,10 +407,10 @@ package android {
field public static final int content = 16843355; // 0x101025b
field public static final int contentAuthority = 16843408; // 0x1010290
field public static final int contentDescription = 16843379; // 0x1010273
- field public static final int controlX1 = 16843771; // 0x10103fb
- field public static final int controlX2 = 16843773; // 0x10103fd
- field public static final int controlY1 = 16843772; // 0x10103fc
- field public static final int controlY2 = 16843774; // 0x10103fe
+ field public static final int controlX1 = 16843799; // 0x1010417
+ field public static final int controlX2 = 16843801; // 0x1010419
+ field public static final int controlY1 = 16843800; // 0x1010418
+ field public static final int controlY2 = 16843802; // 0x101041a
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
field public static final int customNavigationLayout = 16843474; // 0x10102d2
@@ -471,6 +473,7 @@ package android {
field public static final int dropDownWidth = 16843362; // 0x1010262
field public static final int duplicateParentState = 16842985; // 0x10100e9
field public static final int duration = 16843160; // 0x1010198
+ field public static final int durations = 16843814; // 0x1010426
field public static final int editTextBackground = 16843602; // 0x1010352
field public static final int editTextColor = 16843601; // 0x1010351
field public static final int editTextPreferenceStyle = 16842898; // 0x1010092
@@ -511,13 +514,15 @@ package android {
field public static final int fastScrollOverlayPosition = 16843578; // 0x101033a
field public static final int fastScrollPreviewBackgroundLeft = 16843575; // 0x1010337
field public static final int fastScrollPreviewBackgroundRight = 16843576; // 0x1010338
- field public static final int fastScrollStyle = 16843766; // 0x10103f6
+ field public static final int fastScrollStyle = 16843794; // 0x1010412
field public static final int fastScrollTextColor = 16843609; // 0x1010359
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
+ field public static final int fill = 16843809; // 0x1010421
field public static final int fillAfter = 16843197; // 0x10101bd
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillEnabled = 16843343; // 0x101024f
+ field public static final int fillOpacity = 16843808; // 0x1010420
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -537,7 +542,7 @@ package android {
field public static final int format12Hour = 16843722; // 0x10103ca
field public static final int format24Hour = 16843723; // 0x10103cb
field public static final int fragment = 16843491; // 0x10102e3
- field public static final int fragmentBreadCrumbsStyle = 16843765; // 0x10103f5
+ field public static final int fragmentBreadCrumbsStyle = 16843793; // 0x1010411
field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
field public static final int fragmentCloseExitAnimation = 16843496; // 0x10102e8
field public static final int fragmentFadeEnterAnimation = 16843497; // 0x10102e9
@@ -666,6 +671,34 @@ package android {
field public static final int keyboardMode = 16843341; // 0x101024d
field public static final int keycode = 16842949; // 0x10100c5
field public static final int killAfterRestore = 16843420; // 0x101029c
+ field public static final int l_resource_pad1 = 16843792; // 0x1010410
+ field public static final int l_resource_pad10 = 16843783; // 0x1010407
+ field public static final int l_resource_pad11 = 16843782; // 0x1010406
+ field public static final int l_resource_pad12 = 16843781; // 0x1010405
+ field public static final int l_resource_pad13 = 16843780; // 0x1010404
+ field public static final int l_resource_pad14 = 16843779; // 0x1010403
+ field public static final int l_resource_pad15 = 16843778; // 0x1010402
+ field public static final int l_resource_pad16 = 16843777; // 0x1010401
+ field public static final int l_resource_pad17 = 16843776; // 0x1010400
+ field public static final int l_resource_pad18 = 16843775; // 0x10103ff
+ field public static final int l_resource_pad19 = 16843774; // 0x10103fe
+ field public static final int l_resource_pad2 = 16843791; // 0x101040f
+ field public static final int l_resource_pad20 = 16843773; // 0x10103fd
+ field public static final int l_resource_pad21 = 16843772; // 0x10103fc
+ field public static final int l_resource_pad22 = 16843771; // 0x10103fb
+ field public static final int l_resource_pad23 = 16843770; // 0x10103fa
+ field public static final int l_resource_pad24 = 16843769; // 0x10103f9
+ field public static final int l_resource_pad25 = 16843768; // 0x10103f8
+ field public static final int l_resource_pad26 = 16843767; // 0x10103f7
+ field public static final int l_resource_pad27 = 16843766; // 0x10103f6
+ field public static final int l_resource_pad28 = 16843765; // 0x10103f5
+ field public static final int l_resource_pad3 = 16843790; // 0x101040e
+ field public static final int l_resource_pad4 = 16843789; // 0x101040d
+ field public static final int l_resource_pad5 = 16843788; // 0x101040c
+ field public static final int l_resource_pad6 = 16843787; // 0x101040b
+ field public static final int l_resource_pad7 = 16843786; // 0x101040a
+ field public static final int l_resource_pad8 = 16843785; // 0x1010409
+ field public static final int l_resource_pad9 = 16843784; // 0x1010408
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field public static final int labelTextSize = 16843317; // 0x1010235
@@ -721,6 +754,7 @@ package android {
field public static final int layout_x = 16843135; // 0x101017f
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
+ field public static final int limitTo = 16843823; // 0x101042f
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -823,6 +857,7 @@ package android {
field public static final int parentActivityName = 16843687; // 0x10103a7
field public static final deprecated int password = 16843100; // 0x101015c
field public static final int path = 16842794; // 0x101002a
+ field public static final int pathData = 16843810; // 0x1010422
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
field public static final int permission = 16842758; // 0x1010006
@@ -832,7 +867,7 @@ package android {
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
- field public static final int pinned = 16843778; // 0x1010402
+ field public static final int pinned = 16843825; // 0x1010431
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
field public static final int popupAnimationStyle = 16843465; // 0x10102c9
@@ -887,6 +922,7 @@ package android {
field public static final int readPermission = 16842759; // 0x1010007
field public static final int repeatCount = 16843199; // 0x10101bf
field public static final int repeatMode = 16843200; // 0x10101c0
+ field public static final int repeatStyle = 16843816; // 0x1010428
field public static final int reqFiveWayNav = 16843314; // 0x1010232
field public static final int reqHardKeyboard = 16843305; // 0x1010229
field public static final int reqKeyboardType = 16843304; // 0x1010228
@@ -896,7 +932,7 @@ package android {
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
- field public static final int requiredForProfile = 16843777; // 0x1010401
+ field public static final int requiredForProfile = 16843824; // 0x1010430
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
field public static final int resizeMode = 16843619; // 0x1010363
@@ -960,6 +996,7 @@ package android {
field public static final int selectableItemBackground = 16843534; // 0x101030e
field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
+ field public static final int sequence = 16843815; // 0x1010427
field public static final int settingsActivity = 16843301; // 0x1010225
field public static final int shadowColor = 16843105; // 0x1010161
field public static final int shadowDx = 16843106; // 0x1010162
@@ -967,7 +1004,7 @@ package android {
field public static final int shadowRadius = 16843108; // 0x1010164
field public static final int shape = 16843162; // 0x101019a
field public static final int shareInterpolator = 16843195; // 0x10101bb
- field public static final int sharedElementName = 16843775; // 0x10103ff
+ field public static final int sharedElementName = 16843803; // 0x101041b
field public static final int sharedUserId = 16842763; // 0x101000b
field public static final int sharedUserLabel = 16843361; // 0x1010261
field public static final int shouldDisableView = 16843246; // 0x10101ee
@@ -1031,6 +1068,10 @@ package android {
field public static final int streamType = 16843273; // 0x1010209
field public static final int stretchColumns = 16843081; // 0x1010149
field public static final int stretchMode = 16843030; // 0x1010116
+ field public static final int stroke = 16843811; // 0x1010423
+ field public static final int strokeLineCap = 16843820; // 0x101042c
+ field public static final int strokeOpacity = 16843812; // 0x1010424
+ field public static final int strokeWidth = 16843813; // 0x1010425
field public static final int subtitle = 16843473; // 0x10102d1
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
@@ -1144,7 +1185,7 @@ package android {
field public static final int tileMode = 16843265; // 0x1010201
field public static final int timeZone = 16843724; // 0x10103cc
field public static final int tint = 16843041; // 0x1010121
- field public static final int tintMode = 16843770; // 0x10103fa
+ field public static final int tintMode = 16843798; // 0x1010416
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
field public static final int titleTextStyle = 16843512; // 0x10102f8
@@ -1166,11 +1207,15 @@ package android {
field public static final int transformPivotX = 16843552; // 0x1010320
field public static final int transformPivotY = 16843553; // 0x1010321
field public static final int transition = 16843743; // 0x10103df
- field public static final int transitionGroup = 16843776; // 0x1010400
+ field public static final int transitionGroup = 16843804; // 0x101041c
field public static final int transitionOrdering = 16843744; // 0x10103e0
field public static final int translationX = 16843554; // 0x1010322
field public static final int translationY = 16843555; // 0x1010323
- field public static final int translationZ = 16843769; // 0x10103f9
+ field public static final int translationZ = 16843797; // 0x1010415
+ field public static final int trigger = 16843805; // 0x101041d
+ field public static final int trimPathEnd = 16843818; // 0x101042a
+ field public static final int trimPathOffset = 16843819; // 0x101042b
+ field public static final int trimPathStart = 16843817; // 0x1010429
field public static final int type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -1195,6 +1240,8 @@ package android {
field public static final int verticalGap = 16843328; // 0x1010240
field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
field public static final int verticalSpacing = 16843029; // 0x1010115
+ field public static final int viewportHeight = 16843807; // 0x101041f
+ field public static final int viewportWidth = 16843806; // 0x101041e
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1227,8 +1274,8 @@ package android {
field public static final int windowBackground = 16842836; // 0x1010054
field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
field public static final int windowContentOverlay = 16842841; // 0x1010059
- field public static final int windowContentTransitionManager = 16843768; // 0x10103f8
- field public static final int windowContentTransitions = 16843767; // 0x10103f7
+ field public static final int windowContentTransitionManager = 16843796; // 0x1010414
+ field public static final int windowContentTransitions = 16843795; // 0x1010413
field public static final int windowDisablePreview = 16843298; // 0x1010222
field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
field public static final int windowEnterAnimation = 16842932; // 0x10100b4
@@ -1301,10 +1348,20 @@ package android {
field public static final int app_icon_size = 17104896; // 0x1050000
field public static final int dialog_min_width_major = 17104899; // 0x1050003
field public static final int dialog_min_width_minor = 17104900; // 0x1050004
+ field public static final int l_resource_pad1 = 17104912; // 0x1050010
+ field public static final int l_resource_pad10 = 17104903; // 0x1050007
+ field public static final int l_resource_pad2 = 17104911; // 0x105000f
+ field public static final int l_resource_pad3 = 17104910; // 0x105000e
+ field public static final int l_resource_pad4 = 17104909; // 0x105000d
+ field public static final int l_resource_pad5 = 17104908; // 0x105000c
+ field public static final int l_resource_pad6 = 17104907; // 0x105000b
+ field public static final int l_resource_pad7 = 17104906; // 0x105000a
+ field public static final int l_resource_pad8 = 17104905; // 0x1050009
+ field public static final int l_resource_pad9 = 17104904; // 0x1050008
field public static final int notification_large_icon_height = 17104902; // 0x1050006
field public static final int notification_large_icon_width = 17104901; // 0x1050005
- field public static final int recents_thumbnail_height = 17104903; // 0x1050007
- field public static final int recents_thumbnail_width = 17104904; // 0x1050008
+ field public static final int recents_thumbnail_height = 17104913; // 0x1050011
+ field public static final int recents_thumbnail_width = 17104914; // 0x1050012
field public static final int thumbnail_height = 17104897; // 0x1050001
field public static final int thumbnail_width = 17104898; // 0x1050002
}
@@ -1518,7 +1575,27 @@ package android {
field public static final int inputArea = 16908318; // 0x102001e
field public static final int inputExtractEditText = 16908325; // 0x1020025
field public static final int keyboardView = 16908326; // 0x1020026
+ field public static final int l_resource_pad1 = 16908352; // 0x1020040
+ field public static final int l_resource_pad10 = 16908343; // 0x1020037
+ field public static final int l_resource_pad11 = 16908342; // 0x1020036
+ field public static final int l_resource_pad12 = 16908341; // 0x1020035
+ field public static final int l_resource_pad13 = 16908340; // 0x1020034
+ field public static final int l_resource_pad14 = 16908339; // 0x1020033
+ field public static final int l_resource_pad15 = 16908338; // 0x1020032
+ field public static final int l_resource_pad16 = 16908337; // 0x1020031
+ field public static final int l_resource_pad17 = 16908336; // 0x1020030
+ field public static final int l_resource_pad18 = 16908335; // 0x102002f
+ field public static final int l_resource_pad19 = 16908334; // 0x102002e
+ field public static final int l_resource_pad2 = 16908351; // 0x102003f
+ field public static final int l_resource_pad3 = 16908350; // 0x102003e
+ field public static final int l_resource_pad4 = 16908349; // 0x102003d
+ field public static final int l_resource_pad5 = 16908348; // 0x102003c
+ field public static final int l_resource_pad6 = 16908347; // 0x102003b
+ field public static final int l_resource_pad7 = 16908346; // 0x102003a
+ field public static final int l_resource_pad8 = 16908345; // 0x1020039
+ field public static final int l_resource_pad9 = 16908344; // 0x1020038
field public static final int list = 16908298; // 0x102000a
+ field public static final int mask = 16908354; // 0x1020042
field public static final int message = 16908299; // 0x102000b
field public static final int paste = 16908322; // 0x1020022
field public static final int primary = 16908300; // 0x102000c
@@ -1527,7 +1604,7 @@ package android {
field public static final int selectAll = 16908319; // 0x102001f
field public static final int selectTextMode = 16908333; // 0x102002d
field public static final int selectedIcon = 16908302; // 0x102000e
- field public static final int shared_element_name = 16908334; // 0x102002e
+ field public static final int shared_element_name = 16908353; // 0x1020041
field public static final int startSelectingText = 16908328; // 0x1020028
field public static final int stopSelectingText = 16908329; // 0x1020029
field public static final int summary = 16908304; // 0x1020010
@@ -1742,36 +1819,48 @@ package android {
field public static final int TextAppearance_Large_Inverse = 16973891; // 0x1030043
field public static final int TextAppearance_Medium = 16973892; // 0x1030044
field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045
- field public static final int TextAppearance_Quantum = 16974318; // 0x10301ee
- field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974319; // 0x10301ef
- field public static final int TextAppearance_Quantum_Inverse = 16974320; // 0x10301f0
- field public static final int TextAppearance_Quantum_Large = 16974321; // 0x10301f1
- field public static final int TextAppearance_Quantum_Large_Inverse = 16974322; // 0x10301f2
- field public static final int TextAppearance_Quantum_Medium = 16974323; // 0x10301f3
- field public static final int TextAppearance_Quantum_Medium_Inverse = 16974324; // 0x10301f4
- field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974325; // 0x10301f5
- field public static final int TextAppearance_Quantum_SearchResult_Title = 16974326; // 0x10301f6
- field public static final int TextAppearance_Quantum_Small = 16974327; // 0x10301f7
- field public static final int TextAppearance_Quantum_Small_Inverse = 16974328; // 0x10301f8
- field public static final int TextAppearance_Quantum_Widget = 16974330; // 0x10301fa
- field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974331; // 0x10301fb
- field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974332; // 0x10301fc
- field public static final int TextAppearance_Quantum_Widget_ActionBar_Title = 16974333; // 0x10301fd
- field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle = 16974334; // 0x10301fe
- field public static final int TextAppearance_Quantum_Widget_ActionMode_Title = 16974335; // 0x10301ff
- field public static final int TextAppearance_Quantum_Widget_Button = 16974336; // 0x1030200
- field public static final int TextAppearance_Quantum_Widget_DropDownHint = 16974337; // 0x1030201
- field public static final int TextAppearance_Quantum_Widget_DropDownItem = 16974338; // 0x1030202
- field public static final int TextAppearance_Quantum_Widget_EditText = 16974339; // 0x1030203
- field public static final int TextAppearance_Quantum_Widget_IconMenu_Item = 16974340; // 0x1030204
- field public static final int TextAppearance_Quantum_Widget_PopupMenu = 16974341; // 0x1030205
- field public static final int TextAppearance_Quantum_Widget_PopupMenu_Large = 16974342; // 0x1030206
- field public static final int TextAppearance_Quantum_Widget_PopupMenu_Small = 16974343; // 0x1030207
- field public static final int TextAppearance_Quantum_Widget_TabWidget = 16974344; // 0x1030208
- field public static final int TextAppearance_Quantum_Widget_TextView = 16974345; // 0x1030209
- field public static final int TextAppearance_Quantum_Widget_TextView_PopupMenu = 16974346; // 0x103020a
- field public static final int TextAppearance_Quantum_Widget_TextView_SpinnerItem = 16974347; // 0x103020b
- field public static final int TextAppearance_Quantum_WindowTitle = 16974329; // 0x10301f9
+ field public static final int TextAppearance_Quantum = 16974346; // 0x103020a
+ field public static final int TextAppearance_Quantum_Body1 = 16974534; // 0x10302c6
+ field public static final int TextAppearance_Quantum_Body2 = 16974533; // 0x10302c5
+ field public static final int TextAppearance_Quantum_Button = 16974537; // 0x10302c9
+ field public static final int TextAppearance_Quantum_Caption = 16974535; // 0x10302c7
+ field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974347; // 0x103020b
+ field public static final int TextAppearance_Quantum_Display1 = 16974529; // 0x10302c1
+ field public static final int TextAppearance_Quantum_Display2 = 16974528; // 0x10302c0
+ field public static final int TextAppearance_Quantum_Display3 = 16974527; // 0x10302bf
+ field public static final int TextAppearance_Quantum_Display4 = 16974526; // 0x10302be
+ field public static final int TextAppearance_Quantum_Headline = 16974530; // 0x10302c2
+ field public static final int TextAppearance_Quantum_Inverse = 16974348; // 0x103020c
+ field public static final int TextAppearance_Quantum_Large = 16974349; // 0x103020d
+ field public static final int TextAppearance_Quantum_Large_Inverse = 16974350; // 0x103020e
+ field public static final int TextAppearance_Quantum_Medium = 16974351; // 0x103020f
+ field public static final int TextAppearance_Quantum_Medium_Inverse = 16974352; // 0x1030210
+ field public static final int TextAppearance_Quantum_Menu = 16974536; // 0x10302c8
+ field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974353; // 0x1030211
+ field public static final int TextAppearance_Quantum_SearchResult_Title = 16974354; // 0x1030212
+ field public static final int TextAppearance_Quantum_Small = 16974355; // 0x1030213
+ field public static final int TextAppearance_Quantum_Small_Inverse = 16974356; // 0x1030214
+ field public static final int TextAppearance_Quantum_Subhead = 16974532; // 0x10302c4
+ field public static final int TextAppearance_Quantum_Title = 16974531; // 0x10302c3
+ field public static final int TextAppearance_Quantum_Widget = 16974358; // 0x1030216
+ field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974359; // 0x1030217
+ field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974360; // 0x1030218
+ field public static final int TextAppearance_Quantum_Widget_ActionBar_Title = 16974361; // 0x1030219
+ field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle = 16974362; // 0x103021a
+ field public static final int TextAppearance_Quantum_Widget_ActionMode_Title = 16974363; // 0x103021b
+ field public static final int TextAppearance_Quantum_Widget_Button = 16974364; // 0x103021c
+ field public static final int TextAppearance_Quantum_Widget_DropDownHint = 16974365; // 0x103021d
+ field public static final int TextAppearance_Quantum_Widget_DropDownItem = 16974366; // 0x103021e
+ field public static final int TextAppearance_Quantum_Widget_EditText = 16974367; // 0x103021f
+ field public static final int TextAppearance_Quantum_Widget_IconMenu_Item = 16974368; // 0x1030220
+ field public static final int TextAppearance_Quantum_Widget_PopupMenu = 16974369; // 0x1030221
+ field public static final int TextAppearance_Quantum_Widget_PopupMenu_Large = 16974370; // 0x1030222
+ field public static final int TextAppearance_Quantum_Widget_PopupMenu_Small = 16974371; // 0x1030223
+ field public static final int TextAppearance_Quantum_Widget_TabWidget = 16974372; // 0x1030224
+ field public static final int TextAppearance_Quantum_Widget_TextView = 16974373; // 0x1030225
+ field public static final int TextAppearance_Quantum_Widget_TextView_PopupMenu = 16974374; // 0x1030226
+ field public static final int TextAppearance_Quantum_Widget_TextView_SpinnerItem = 16974375; // 0x1030227
+ field public static final int TextAppearance_Quantum_WindowTitle = 16974357; // 0x1030215
field public static final int TextAppearance_Small = 16973894; // 0x1030046
field public static final int TextAppearance_Small_Inverse = 16973895; // 0x1030047
field public static final int TextAppearance_StatusBar_EventContent = 16973927; // 0x1030067
@@ -1866,34 +1955,34 @@ package android {
field public static final int Theme_NoTitleBar_Fullscreen = 16973831; // 0x1030007
field public static final int Theme_NoTitleBar_OverlayActionModes = 16973930; // 0x103006a
field public static final int Theme_Panel = 16973913; // 0x1030059
- field public static final int Theme_Quantum = 16974348; // 0x103020c
- field public static final int Theme_Quantum_Dialog = 16974349; // 0x103020d
- field public static final int Theme_Quantum_DialogWhenLarge = 16974353; // 0x1030211
- field public static final int Theme_Quantum_DialogWhenLarge_NoActionBar = 16974354; // 0x1030212
- field public static final int Theme_Quantum_Dialog_MinWidth = 16974350; // 0x103020e
- field public static final int Theme_Quantum_Dialog_NoActionBar = 16974351; // 0x103020f
- field public static final int Theme_Quantum_Dialog_NoActionBar_MinWidth = 16974352; // 0x1030210
- field public static final int Theme_Quantum_InputMethod = 16974355; // 0x1030213
- field public static final int Theme_Quantum_Light = 16974363; // 0x103021b
- field public static final int Theme_Quantum_Light_DarkActionBar = 16974364; // 0x103021c
- field public static final int Theme_Quantum_Light_Dialog = 16974365; // 0x103021d
- field public static final int Theme_Quantum_Light_DialogWhenLarge = 16974369; // 0x1030221
- field public static final int Theme_Quantum_Light_DialogWhenLarge_NoActionBar = 16974370; // 0x1030222
- field public static final int Theme_Quantum_Light_Dialog_MinWidth = 16974366; // 0x103021e
- field public static final int Theme_Quantum_Light_Dialog_NoActionBar = 16974367; // 0x103021f
- field public static final int Theme_Quantum_Light_Dialog_NoActionBar_MinWidth = 16974368; // 0x1030220
- field public static final int Theme_Quantum_Light_NoActionBar = 16974371; // 0x1030223
- field public static final int Theme_Quantum_Light_NoActionBar_Fullscreen = 16974372; // 0x1030224
- field public static final int Theme_Quantum_Light_NoActionBar_Overscan = 16974373; // 0x1030225
- field public static final int Theme_Quantum_Light_NoActionBar_TranslucentDecor = 16974374; // 0x1030226
- field public static final int Theme_Quantum_Light_Panel = 16974375; // 0x1030227
- field public static final int Theme_Quantum_NoActionBar = 16974356; // 0x1030214
- field public static final int Theme_Quantum_NoActionBar_Fullscreen = 16974357; // 0x1030215
- field public static final int Theme_Quantum_NoActionBar_Overscan = 16974358; // 0x1030216
- field public static final int Theme_Quantum_NoActionBar_TranslucentDecor = 16974359; // 0x1030217
- field public static final int Theme_Quantum_Panel = 16974360; // 0x1030218
- field public static final int Theme_Quantum_Wallpaper = 16974361; // 0x1030219
- field public static final int Theme_Quantum_Wallpaper_NoTitleBar = 16974362; // 0x103021a
+ field public static final int Theme_Quantum = 16974376; // 0x1030228
+ field public static final int Theme_Quantum_Dialog = 16974377; // 0x1030229
+ field public static final int Theme_Quantum_DialogWhenLarge = 16974381; // 0x103022d
+ field public static final int Theme_Quantum_DialogWhenLarge_NoActionBar = 16974382; // 0x103022e
+ field public static final int Theme_Quantum_Dialog_MinWidth = 16974378; // 0x103022a
+ field public static final int Theme_Quantum_Dialog_NoActionBar = 16974379; // 0x103022b
+ field public static final int Theme_Quantum_Dialog_NoActionBar_MinWidth = 16974380; // 0x103022c
+ field public static final int Theme_Quantum_InputMethod = 16974383; // 0x103022f
+ field public static final int Theme_Quantum_Light = 16974391; // 0x1030237
+ field public static final int Theme_Quantum_Light_DarkActionBar = 16974392; // 0x1030238
+ field public static final int Theme_Quantum_Light_Dialog = 16974393; // 0x1030239
+ field public static final int Theme_Quantum_Light_DialogWhenLarge = 16974397; // 0x103023d
+ field public static final int Theme_Quantum_Light_DialogWhenLarge_NoActionBar = 16974398; // 0x103023e
+ field public static final int Theme_Quantum_Light_Dialog_MinWidth = 16974394; // 0x103023a
+ field public static final int Theme_Quantum_Light_Dialog_NoActionBar = 16974395; // 0x103023b
+ field public static final int Theme_Quantum_Light_Dialog_NoActionBar_MinWidth = 16974396; // 0x103023c
+ field public static final int Theme_Quantum_Light_NoActionBar = 16974399; // 0x103023f
+ field public static final int Theme_Quantum_Light_NoActionBar_Fullscreen = 16974400; // 0x1030240
+ field public static final int Theme_Quantum_Light_NoActionBar_Overscan = 16974401; // 0x1030241
+ field public static final int Theme_Quantum_Light_NoActionBar_TranslucentDecor = 16974402; // 0x1030242
+ field public static final int Theme_Quantum_Light_Panel = 16974403; // 0x1030243
+ field public static final int Theme_Quantum_NoActionBar = 16974384; // 0x1030230
+ field public static final int Theme_Quantum_NoActionBar_Fullscreen = 16974385; // 0x1030231
+ field public static final int Theme_Quantum_NoActionBar_Overscan = 16974386; // 0x1030232
+ field public static final int Theme_Quantum_NoActionBar_TranslucentDecor = 16974387; // 0x1030233
+ field public static final int Theme_Quantum_Panel = 16974388; // 0x1030234
+ field public static final int Theme_Quantum_Wallpaper = 16974389; // 0x1030235
+ field public static final int Theme_Quantum_Wallpaper_NoTitleBar = 16974390; // 0x1030236
field public static final int Theme_Translucent = 16973839; // 0x103000f
field public static final int Theme_Translucent_NoTitleBar = 16973840; // 0x1030010
field public static final int Theme_Translucent_NoTitleBar_Fullscreen = 16973841; // 0x1030011
@@ -1950,8 +2039,8 @@ package android {
field public static final int Widget_DeviceDefault_DropDownItem_Spinner = 16974178; // 0x1030162
field public static final int Widget_DeviceDefault_EditText = 16974154; // 0x103014a
field public static final int Widget_DeviceDefault_ExpandableListView = 16974155; // 0x103014b
- field public static final int Widget_DeviceDefault_FastScroll = 16974316; // 0x10301ec
- field public static final int Widget_DeviceDefault_FragmentBreadCrumbs = 16974311; // 0x10301e7
+ field public static final int Widget_DeviceDefault_FastScroll = 16974344; // 0x1030208
+ field public static final int Widget_DeviceDefault_FragmentBreadCrumbs = 16974339; // 0x1030203
field public static final int Widget_DeviceDefault_GridView = 16974156; // 0x103014c
field public static final int Widget_DeviceDefault_HorizontalScrollView = 16974171; // 0x103015b
field public static final int Widget_DeviceDefault_ImageButton = 16974157; // 0x103014d
@@ -1985,8 +2074,8 @@ package android {
field public static final int Widget_DeviceDefault_Light_DropDownItem_Spinner = 16974233; // 0x1030199
field public static final int Widget_DeviceDefault_Light_EditText = 16974206; // 0x103017e
field public static final int Widget_DeviceDefault_Light_ExpandableListView = 16974207; // 0x103017f
- field public static final int Widget_DeviceDefault_Light_FastScroll = 16974317; // 0x10301ed
- field public static final int Widget_DeviceDefault_Light_FragmentBreadCrumbs = 16974312; // 0x10301e8
+ field public static final int Widget_DeviceDefault_Light_FastScroll = 16974345; // 0x1030209
+ field public static final int Widget_DeviceDefault_Light_FragmentBreadCrumbs = 16974340; // 0x1030204
field public static final int Widget_DeviceDefault_Light_GridView = 16974208; // 0x1030180
field public static final int Widget_DeviceDefault_Light_HorizontalScrollView = 16974226; // 0x1030192
field public static final int Widget_DeviceDefault_Light_ImageButton = 16974209; // 0x1030181
@@ -2043,7 +2132,7 @@ package android {
field public static final int Widget_DropDownItem_Spinner = 16973868; // 0x103002c
field public static final int Widget_EditText = 16973859; // 0x1030023
field public static final int Widget_ExpandableListView = 16973860; // 0x1030024
- field public static final int Widget_FastScroll = 16974313; // 0x10301e9
+ field public static final int Widget_FastScroll = 16974341; // 0x1030205
field public static final int Widget_FragmentBreadCrumbs = 16973961; // 0x1030089
field public static final int Widget_Gallery = 16973877; // 0x1030035
field public static final int Widget_GridView = 16973874; // 0x1030032
@@ -2075,8 +2164,8 @@ package android {
field public static final int Widget_Holo_DropDownItem_Spinner = 16973995; // 0x10300ab
field public static final int Widget_Holo_EditText = 16973971; // 0x1030093
field public static final int Widget_Holo_ExpandableListView = 16973972; // 0x1030094
- field public static final int Widget_Holo_FastScroll = 16974314; // 0x10301ea
- field public static final int Widget_Holo_FragmentBreadCrumbs = 16974309; // 0x10301e5
+ field public static final int Widget_Holo_FastScroll = 16974342; // 0x1030206
+ field public static final int Widget_Holo_FragmentBreadCrumbs = 16974337; // 0x1030201
field public static final int Widget_Holo_GridView = 16973973; // 0x1030095
field public static final int Widget_Holo_HorizontalScrollView = 16973988; // 0x10300a4
field public static final int Widget_Holo_ImageButton = 16973974; // 0x1030096
@@ -2097,6 +2186,7 @@ package android {
field public static final int Widget_Holo_Light_ActionMode_Inverse = 16974119; // 0x1030127
field public static final int Widget_Holo_Light_AutoCompleteTextView = 16974011; // 0x10300bb
field public static final int Widget_Holo_Light_Button = 16974006; // 0x10300b6
+ field public static final int Widget_Holo_Light_Button_Borderless = 16974538; // 0x10302ca
field public static final int Widget_Holo_Light_Button_Borderless_Small = 16974107; // 0x103011b
field public static final int Widget_Holo_Light_Button_Inset = 16974008; // 0x10300b8
field public static final int Widget_Holo_Light_Button_Small = 16974007; // 0x10300b7
@@ -2110,8 +2200,8 @@ package android {
field public static final int Widget_Holo_Light_DropDownItem_Spinner = 16974041; // 0x10300d9
field public static final int Widget_Holo_Light_EditText = 16974014; // 0x10300be
field public static final int Widget_Holo_Light_ExpandableListView = 16974015; // 0x10300bf
- field public static final int Widget_Holo_Light_FastScroll = 16974315; // 0x10301eb
- field public static final int Widget_Holo_Light_FragmentBreadCrumbs = 16974310; // 0x10301e6
+ field public static final int Widget_Holo_Light_FastScroll = 16974343; // 0x1030207
+ field public static final int Widget_Holo_Light_FragmentBreadCrumbs = 16974338; // 0x1030202
field public static final int Widget_Holo_Light_GridView = 16974016; // 0x10300c0
field public static final int Widget_Holo_Light_HorizontalScrollView = 16974034; // 0x10300d2
field public static final int Widget_Holo_Light_ImageButton = 16974017; // 0x10300c1
@@ -2181,128 +2271,128 @@ package android {
field public static final int Widget_ProgressBar_Large_Inverse = 16973916; // 0x103005c
field public static final int Widget_ProgressBar_Small = 16973854; // 0x103001e
field public static final int Widget_ProgressBar_Small_Inverse = 16973917; // 0x103005d
- field public static final int Widget_Quantum = 16974376; // 0x1030228
- field public static final int Widget_Quantum_ActionBar = 16974377; // 0x1030229
- field public static final int Widget_Quantum_ActionBar_Solid = 16974378; // 0x103022a
- field public static final int Widget_Quantum_ActionBar_TabBar = 16974379; // 0x103022b
- field public static final int Widget_Quantum_ActionBar_TabText = 16974380; // 0x103022c
- field public static final int Widget_Quantum_ActionBar_TabView = 16974381; // 0x103022d
- field public static final int Widget_Quantum_ActionButton = 16974382; // 0x103022e
- field public static final int Widget_Quantum_ActionButton_CloseMode = 16974383; // 0x103022f
- field public static final int Widget_Quantum_ActionButton_Overflow = 16974384; // 0x1030230
- field public static final int Widget_Quantum_ActionButton_TextButton = 16974385; // 0x1030231
- field public static final int Widget_Quantum_ActionMode = 16974386; // 0x1030232
- field public static final int Widget_Quantum_AutoCompleteTextView = 16974387; // 0x1030233
- field public static final int Widget_Quantum_Button = 16974388; // 0x1030234
- field public static final int Widget_Quantum_ButtonBar = 16974394; // 0x103023a
- field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974395; // 0x103023b
- field public static final int Widget_Quantum_Button_Borderless = 16974389; // 0x1030235
- field public static final int Widget_Quantum_Button_Borderless_Small = 16974390; // 0x1030236
- field public static final int Widget_Quantum_Button_Inset = 16974391; // 0x1030237
- field public static final int Widget_Quantum_Button_Paper = 16974494; // 0x103029e
- field public static final int Widget_Quantum_Button_Paper_Color = 16974495; // 0x103029f
- field public static final int Widget_Quantum_Button_Small = 16974392; // 0x1030238
- field public static final int Widget_Quantum_Button_Toggle = 16974393; // 0x1030239
- field public static final int Widget_Quantum_CalendarView = 16974396; // 0x103023c
- field public static final int Widget_Quantum_CheckedTextView = 16974397; // 0x103023d
- field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974398; // 0x103023e
- field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974399; // 0x103023f
- field public static final int Widget_Quantum_CompoundButton_Star = 16974400; // 0x1030240
- field public static final int Widget_Quantum_DatePicker = 16974401; // 0x1030241
- field public static final int Widget_Quantum_DropDownItem = 16974402; // 0x1030242
- field public static final int Widget_Quantum_DropDownItem_Spinner = 16974403; // 0x1030243
- field public static final int Widget_Quantum_EditText = 16974404; // 0x1030244
- field public static final int Widget_Quantum_ExpandableListView = 16974405; // 0x1030245
- field public static final int Widget_Quantum_FastScroll = 16974406; // 0x1030246
- field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974407; // 0x1030247
- field public static final int Widget_Quantum_GridView = 16974408; // 0x1030248
- field public static final int Widget_Quantum_HorizontalScrollView = 16974409; // 0x1030249
- field public static final int Widget_Quantum_ImageButton = 16974410; // 0x103024a
- field public static final int Widget_Quantum_Light = 16974435; // 0x1030263
- field public static final int Widget_Quantum_Light_ActionBar = 16974436; // 0x1030264
- field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974437; // 0x1030265
- field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974438; // 0x1030266
- field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974439; // 0x1030267
- field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974440; // 0x1030268
- field public static final int Widget_Quantum_Light_ActionButton = 16974441; // 0x1030269
- field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974442; // 0x103026a
- field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974443; // 0x103026b
- field public static final int Widget_Quantum_Light_ActionMode = 16974444; // 0x103026c
- field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974445; // 0x103026d
- field public static final int Widget_Quantum_Light_Button = 16974446; // 0x103026e
- field public static final int Widget_Quantum_Light_ButtonBar = 16974451; // 0x1030273
- field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974452; // 0x1030274
- field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974447; // 0x103026f
- field public static final int Widget_Quantum_Light_Button_Inset = 16974448; // 0x1030270
- field public static final int Widget_Quantum_Light_Button_Paper = 16974496; // 0x10302a0
- field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974497; // 0x10302a1
- field public static final int Widget_Quantum_Light_Button_Small = 16974449; // 0x1030271
- field public static final int Widget_Quantum_Light_Button_Toggle = 16974450; // 0x1030272
- field public static final int Widget_Quantum_Light_CalendarView = 16974453; // 0x1030275
- field public static final int Widget_Quantum_Light_CheckedTextView = 16974454; // 0x1030276
- field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974455; // 0x1030277
- field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974456; // 0x1030278
- field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974457; // 0x1030279
- field public static final int Widget_Quantum_Light_DropDownItem = 16974458; // 0x103027a
- field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974459; // 0x103027b
- field public static final int Widget_Quantum_Light_EditText = 16974460; // 0x103027c
- field public static final int Widget_Quantum_Light_ExpandableListView = 16974461; // 0x103027d
- field public static final int Widget_Quantum_Light_FastScroll = 16974462; // 0x103027e
- field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974463; // 0x103027f
- field public static final int Widget_Quantum_Light_GridView = 16974464; // 0x1030280
- field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974465; // 0x1030281
- field public static final int Widget_Quantum_Light_ImageButton = 16974466; // 0x1030282
- field public static final int Widget_Quantum_Light_ListPopupWindow = 16974467; // 0x1030283
- field public static final int Widget_Quantum_Light_ListView = 16974468; // 0x1030284
- field public static final int Widget_Quantum_Light_ListView_DropDown = 16974469; // 0x1030285
- field public static final int Widget_Quantum_Light_MediaRouteButton = 16974470; // 0x1030286
- field public static final int Widget_Quantum_Light_PopupMenu = 16974471; // 0x1030287
- field public static final int Widget_Quantum_Light_PopupWindow = 16974472; // 0x1030288
- field public static final int Widget_Quantum_Light_ProgressBar = 16974473; // 0x1030289
- field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974474; // 0x103028a
- field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974475; // 0x103028b
- field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974476; // 0x103028c
- field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974477; // 0x103028d
- field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974478; // 0x103028e
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974479; // 0x103028f
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974480; // 0x1030290
- field public static final int Widget_Quantum_Light_RatingBar = 16974481; // 0x1030291
- field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974482; // 0x1030292
- field public static final int Widget_Quantum_Light_RatingBar_Small = 16974483; // 0x1030293
- field public static final int Widget_Quantum_Light_ScrollView = 16974484; // 0x1030294
- field public static final int Widget_Quantum_Light_SeekBar = 16974485; // 0x1030295
- field public static final int Widget_Quantum_Light_SegmentedButton = 16974486; // 0x1030296
- field public static final int Widget_Quantum_Light_Spinner = 16974487; // 0x1030297
- field public static final int Widget_Quantum_Light_Tab = 16974488; // 0x1030298
- field public static final int Widget_Quantum_Light_TabWidget = 16974489; // 0x1030299
- field public static final int Widget_Quantum_Light_TextView = 16974490; // 0x103029a
- field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974491; // 0x103029b
- field public static final int Widget_Quantum_Light_WebTextView = 16974492; // 0x103029c
- field public static final int Widget_Quantum_Light_WebView = 16974493; // 0x103029d
- field public static final int Widget_Quantum_ListPopupWindow = 16974411; // 0x103024b
- field public static final int Widget_Quantum_ListView = 16974412; // 0x103024c
- field public static final int Widget_Quantum_ListView_DropDown = 16974413; // 0x103024d
- field public static final int Widget_Quantum_MediaRouteButton = 16974414; // 0x103024e
- field public static final int Widget_Quantum_PopupMenu = 16974415; // 0x103024f
- field public static final int Widget_Quantum_PopupWindow = 16974416; // 0x1030250
- field public static final int Widget_Quantum_ProgressBar = 16974417; // 0x1030251
- field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974418; // 0x1030252
- field public static final int Widget_Quantum_ProgressBar_Large = 16974419; // 0x1030253
- field public static final int Widget_Quantum_ProgressBar_Small = 16974420; // 0x1030254
- field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974421; // 0x1030255
- field public static final int Widget_Quantum_RatingBar = 16974422; // 0x1030256
- field public static final int Widget_Quantum_RatingBar_Indicator = 16974423; // 0x1030257
- field public static final int Widget_Quantum_RatingBar_Small = 16974424; // 0x1030258
- field public static final int Widget_Quantum_ScrollView = 16974425; // 0x1030259
- field public static final int Widget_Quantum_SeekBar = 16974426; // 0x103025a
- field public static final int Widget_Quantum_SegmentedButton = 16974427; // 0x103025b
- field public static final int Widget_Quantum_Spinner = 16974428; // 0x103025c
- field public static final int Widget_Quantum_Tab = 16974429; // 0x103025d
- field public static final int Widget_Quantum_TabWidget = 16974430; // 0x103025e
- field public static final int Widget_Quantum_TextView = 16974431; // 0x103025f
- field public static final int Widget_Quantum_TextView_SpinnerItem = 16974432; // 0x1030260
- field public static final int Widget_Quantum_WebTextView = 16974433; // 0x1030261
- field public static final int Widget_Quantum_WebView = 16974434; // 0x1030262
+ field public static final int Widget_Quantum = 16974404; // 0x1030244
+ field public static final int Widget_Quantum_ActionBar = 16974405; // 0x1030245
+ field public static final int Widget_Quantum_ActionBar_Solid = 16974406; // 0x1030246
+ field public static final int Widget_Quantum_ActionBar_TabBar = 16974407; // 0x1030247
+ field public static final int Widget_Quantum_ActionBar_TabText = 16974408; // 0x1030248
+ field public static final int Widget_Quantum_ActionBar_TabView = 16974409; // 0x1030249
+ field public static final int Widget_Quantum_ActionButton = 16974410; // 0x103024a
+ field public static final int Widget_Quantum_ActionButton_CloseMode = 16974411; // 0x103024b
+ field public static final int Widget_Quantum_ActionButton_Overflow = 16974412; // 0x103024c
+ field public static final int Widget_Quantum_ActionButton_TextButton = 16974413; // 0x103024d
+ field public static final int Widget_Quantum_ActionMode = 16974414; // 0x103024e
+ field public static final int Widget_Quantum_AutoCompleteTextView = 16974415; // 0x103024f
+ field public static final int Widget_Quantum_Button = 16974416; // 0x1030250
+ field public static final int Widget_Quantum_ButtonBar = 16974422; // 0x1030256
+ field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974423; // 0x1030257
+ field public static final int Widget_Quantum_Button_Borderless = 16974417; // 0x1030251
+ field public static final int Widget_Quantum_Button_Borderless_Small = 16974418; // 0x1030252
+ field public static final int Widget_Quantum_Button_Inset = 16974419; // 0x1030253
+ field public static final int Widget_Quantum_Button_Paper = 16974522; // 0x10302ba
+ field public static final int Widget_Quantum_Button_Paper_Color = 16974523; // 0x10302bb
+ field public static final int Widget_Quantum_Button_Small = 16974420; // 0x1030254
+ field public static final int Widget_Quantum_Button_Toggle = 16974421; // 0x1030255
+ field public static final int Widget_Quantum_CalendarView = 16974424; // 0x1030258
+ field public static final int Widget_Quantum_CheckedTextView = 16974425; // 0x1030259
+ field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974426; // 0x103025a
+ field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974427; // 0x103025b
+ field public static final int Widget_Quantum_CompoundButton_Star = 16974428; // 0x103025c
+ field public static final int Widget_Quantum_DatePicker = 16974429; // 0x103025d
+ field public static final int Widget_Quantum_DropDownItem = 16974430; // 0x103025e
+ field public static final int Widget_Quantum_DropDownItem_Spinner = 16974431; // 0x103025f
+ field public static final int Widget_Quantum_EditText = 16974432; // 0x1030260
+ field public static final int Widget_Quantum_ExpandableListView = 16974433; // 0x1030261
+ field public static final int Widget_Quantum_FastScroll = 16974434; // 0x1030262
+ field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974435; // 0x1030263
+ field public static final int Widget_Quantum_GridView = 16974436; // 0x1030264
+ field public static final int Widget_Quantum_HorizontalScrollView = 16974437; // 0x1030265
+ field public static final int Widget_Quantum_ImageButton = 16974438; // 0x1030266
+ field public static final int Widget_Quantum_Light = 16974463; // 0x103027f
+ field public static final int Widget_Quantum_Light_ActionBar = 16974464; // 0x1030280
+ field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974465; // 0x1030281
+ field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974466; // 0x1030282
+ field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974467; // 0x1030283
+ field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974468; // 0x1030284
+ field public static final int Widget_Quantum_Light_ActionButton = 16974469; // 0x1030285
+ field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974470; // 0x1030286
+ field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974471; // 0x1030287
+ field public static final int Widget_Quantum_Light_ActionMode = 16974472; // 0x1030288
+ field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974473; // 0x1030289
+ field public static final int Widget_Quantum_Light_Button = 16974474; // 0x103028a
+ field public static final int Widget_Quantum_Light_ButtonBar = 16974479; // 0x103028f
+ field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974480; // 0x1030290
+ field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974475; // 0x103028b
+ field public static final int Widget_Quantum_Light_Button_Inset = 16974476; // 0x103028c
+ field public static final int Widget_Quantum_Light_Button_Paper = 16974524; // 0x10302bc
+ field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974525; // 0x10302bd
+ field public static final int Widget_Quantum_Light_Button_Small = 16974477; // 0x103028d
+ field public static final int Widget_Quantum_Light_Button_Toggle = 16974478; // 0x103028e
+ field public static final int Widget_Quantum_Light_CalendarView = 16974481; // 0x1030291
+ field public static final int Widget_Quantum_Light_CheckedTextView = 16974482; // 0x1030292
+ field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974483; // 0x1030293
+ field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974484; // 0x1030294
+ field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974485; // 0x1030295
+ field public static final int Widget_Quantum_Light_DropDownItem = 16974486; // 0x1030296
+ field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974487; // 0x1030297
+ field public static final int Widget_Quantum_Light_EditText = 16974488; // 0x1030298
+ field public static final int Widget_Quantum_Light_ExpandableListView = 16974489; // 0x1030299
+ field public static final int Widget_Quantum_Light_FastScroll = 16974490; // 0x103029a
+ field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974491; // 0x103029b
+ field public static final int Widget_Quantum_Light_GridView = 16974492; // 0x103029c
+ field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974493; // 0x103029d
+ field public static final int Widget_Quantum_Light_ImageButton = 16974494; // 0x103029e
+ field public static final int Widget_Quantum_Light_ListPopupWindow = 16974495; // 0x103029f
+ field public static final int Widget_Quantum_Light_ListView = 16974496; // 0x10302a0
+ field public static final int Widget_Quantum_Light_ListView_DropDown = 16974497; // 0x10302a1
+ field public static final int Widget_Quantum_Light_MediaRouteButton = 16974498; // 0x10302a2
+ field public static final int Widget_Quantum_Light_PopupMenu = 16974499; // 0x10302a3
+ field public static final int Widget_Quantum_Light_PopupWindow = 16974500; // 0x10302a4
+ field public static final int Widget_Quantum_Light_ProgressBar = 16974501; // 0x10302a5
+ field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974502; // 0x10302a6
+ field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974503; // 0x10302a7
+ field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974504; // 0x10302a8
+ field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974505; // 0x10302a9
+ field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974506; // 0x10302aa
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974507; // 0x10302ab
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974508; // 0x10302ac
+ field public static final int Widget_Quantum_Light_RatingBar = 16974509; // 0x10302ad
+ field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974510; // 0x10302ae
+ field public static final int Widget_Quantum_Light_RatingBar_Small = 16974511; // 0x10302af
+ field public static final int Widget_Quantum_Light_ScrollView = 16974512; // 0x10302b0
+ field public static final int Widget_Quantum_Light_SeekBar = 16974513; // 0x10302b1
+ field public static final int Widget_Quantum_Light_SegmentedButton = 16974514; // 0x10302b2
+ field public static final int Widget_Quantum_Light_Spinner = 16974515; // 0x10302b3
+ field public static final int Widget_Quantum_Light_Tab = 16974516; // 0x10302b4
+ field public static final int Widget_Quantum_Light_TabWidget = 16974517; // 0x10302b5
+ field public static final int Widget_Quantum_Light_TextView = 16974518; // 0x10302b6
+ field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974519; // 0x10302b7
+ field public static final int Widget_Quantum_Light_WebTextView = 16974520; // 0x10302b8
+ field public static final int Widget_Quantum_Light_WebView = 16974521; // 0x10302b9
+ field public static final int Widget_Quantum_ListPopupWindow = 16974439; // 0x1030267
+ field public static final int Widget_Quantum_ListView = 16974440; // 0x1030268
+ field public static final int Widget_Quantum_ListView_DropDown = 16974441; // 0x1030269
+ field public static final int Widget_Quantum_MediaRouteButton = 16974442; // 0x103026a
+ field public static final int Widget_Quantum_PopupMenu = 16974443; // 0x103026b
+ field public static final int Widget_Quantum_PopupWindow = 16974444; // 0x103026c
+ field public static final int Widget_Quantum_ProgressBar = 16974445; // 0x103026d
+ field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974446; // 0x103026e
+ field public static final int Widget_Quantum_ProgressBar_Large = 16974447; // 0x103026f
+ field public static final int Widget_Quantum_ProgressBar_Small = 16974448; // 0x1030270
+ field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974449; // 0x1030271
+ field public static final int Widget_Quantum_RatingBar = 16974450; // 0x1030272
+ field public static final int Widget_Quantum_RatingBar_Indicator = 16974451; // 0x1030273
+ field public static final int Widget_Quantum_RatingBar_Small = 16974452; // 0x1030274
+ field public static final int Widget_Quantum_ScrollView = 16974453; // 0x1030275
+ field public static final int Widget_Quantum_SeekBar = 16974454; // 0x1030276
+ field public static final int Widget_Quantum_SegmentedButton = 16974455; // 0x1030277
+ field public static final int Widget_Quantum_Spinner = 16974456; // 0x1030278
+ field public static final int Widget_Quantum_Tab = 16974457; // 0x1030279
+ field public static final int Widget_Quantum_TabWidget = 16974458; // 0x103027a
+ field public static final int Widget_Quantum_TextView = 16974459; // 0x103027b
+ field public static final int Widget_Quantum_TextView_SpinnerItem = 16974460; // 0x103027c
+ field public static final int Widget_Quantum_WebTextView = 16974461; // 0x103027d
+ field public static final int Widget_Quantum_WebView = 16974462; // 0x103027e
field public static final int Widget_RatingBar = 16973857; // 0x1030021
field public static final int Widget_ScrollView = 16973869; // 0x103002d
field public static final int Widget_SeekBar = 16973856; // 0x1030020
@@ -2313,6 +2403,34 @@ package android {
field public static final int Widget_TextView_PopupMenu = 16973865; // 0x1030029
field public static final int Widget_TextView_SpinnerItem = 16973866; // 0x103002a
field public static final int Widget_WebView = 16973875; // 0x1030033
+ field public static final int l_resource_pad1 = 16974336; // 0x1030200
+ field public static final int l_resource_pad10 = 16974327; // 0x10301f7
+ field public static final int l_resource_pad11 = 16974326; // 0x10301f6
+ field public static final int l_resource_pad12 = 16974325; // 0x10301f5
+ field public static final int l_resource_pad13 = 16974324; // 0x10301f4
+ field public static final int l_resource_pad14 = 16974323; // 0x10301f3
+ field public static final int l_resource_pad15 = 16974322; // 0x10301f2
+ field public static final int l_resource_pad16 = 16974321; // 0x10301f1
+ field public static final int l_resource_pad17 = 16974320; // 0x10301f0
+ field public static final int l_resource_pad18 = 16974319; // 0x10301ef
+ field public static final int l_resource_pad19 = 16974318; // 0x10301ee
+ field public static final int l_resource_pad2 = 16974335; // 0x10301ff
+ field public static final int l_resource_pad20 = 16974317; // 0x10301ed
+ field public static final int l_resource_pad21 = 16974316; // 0x10301ec
+ field public static final int l_resource_pad22 = 16974315; // 0x10301eb
+ field public static final int l_resource_pad23 = 16974314; // 0x10301ea
+ field public static final int l_resource_pad24 = 16974313; // 0x10301e9
+ field public static final int l_resource_pad25 = 16974312; // 0x10301e8
+ field public static final int l_resource_pad26 = 16974311; // 0x10301e7
+ field public static final int l_resource_pad27 = 16974310; // 0x10301e6
+ field public static final int l_resource_pad28 = 16974309; // 0x10301e5
+ field public static final int l_resource_pad3 = 16974334; // 0x10301fe
+ field public static final int l_resource_pad4 = 16974333; // 0x10301fd
+ field public static final int l_resource_pad5 = 16974332; // 0x10301fc
+ field public static final int l_resource_pad6 = 16974331; // 0x10301fb
+ field public static final int l_resource_pad7 = 16974330; // 0x10301fa
+ field public static final int l_resource_pad8 = 16974329; // 0x10301f9
+ field public static final int l_resource_pad9 = 16974328; // 0x10301f8
}
public static final class R.xml {
@@ -6372,6 +6490,7 @@ package android.content {
field public static final java.lang.String USER_SERVICE = "user";
field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
+ field public static final java.lang.String WIFI_HOTSPOT_SERVICE = "wifihotspot";
field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
field public static final java.lang.String WIFI_SERVICE = "wifi";
field public static final java.lang.String WINDOW_SERVICE = "window";
@@ -6803,6 +6922,7 @@ package android.content {
field public static final java.lang.String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
field public static final java.lang.String CATEGORY_LE_DESK_DOCK = "android.intent.category.LE_DESK_DOCK";
field public static final java.lang.String CATEGORY_MONKEY = "android.intent.category.MONKEY";
+ field public static final java.lang.String CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES";
field public static final java.lang.String CATEGORY_OPENABLE = "android.intent.category.OPENABLE";
field public static final java.lang.String CATEGORY_PREFERENCE = "android.intent.category.PREFERENCE";
field public static final java.lang.String CATEGORY_SAMPLE_CODE = "android.intent.category.SAMPLE_CODE";
@@ -10757,10 +10877,6 @@ package android.graphics.drawable {
method public void setPicture(android.graphics.Picture);
}
- public class RevealDrawable extends android.graphics.drawable.LayerDrawable {
- ctor public RevealDrawable(android.graphics.drawable.Drawable[]);
- }
-
public class RotateDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
ctor public RotateDrawable();
method public void draw(android.graphics.Canvas);
@@ -10830,7 +10946,8 @@ package android.graphics.drawable {
method public void addState(int[], android.graphics.drawable.Drawable);
}
- public class TouchFeedbackDrawable extends android.graphics.drawable.DrawableWrapper {
+ public class TouchFeedbackDrawable extends android.graphics.drawable.LayerDrawable {
+ method public android.graphics.Rect getDirtyBounds();
}
public class TransitionDrawable extends android.graphics.drawable.LayerDrawable implements android.graphics.drawable.Drawable.Callback {
@@ -10842,6 +10959,27 @@ package android.graphics.drawable {
method public void startTransition(int);
}
+ public class VectorDrawable extends android.graphics.drawable.Drawable {
+ ctor public VectorDrawable();
+ method public void draw(android.graphics.Canvas);
+ method public float geAnimationFraction();
+ method public int getOpacity();
+ method public int getRepeatCount();
+ method public void setAlpha(int);
+ method public void setAnimationFraction(float);
+ method public void setColorFilter(android.graphics.ColorFilter);
+ method public void setDuration(long);
+ method public void setIntrinsicHeight(int);
+ method public void setIntrinsicWidth(int);
+ method public void setPadding(android.graphics.Rect);
+ method public void setPadding(int, int, int, int);
+ method public void setRepeatCount(int);
+ method public void setRepeatMode(int);
+ method public void start();
+ method public void stop();
+ field public static final int INFINITE = -1; // 0xffffffff
+ }
+
}
package android.graphics.drawable.shapes {
@@ -16063,6 +16201,19 @@ package android.net.wifi {
}
+package android.net.wifi.hotspot {
+
+ public abstract interface IWifiHotspotManager implements android.os.IInterface {
+ method public abstract void test() throws android.os.RemoteException;
+ }
+
+ public class WifiHotspotManager {
+ ctor public WifiHotspotManager(android.content.Context, android.net.wifi.hotspot.IWifiHotspotManager);
+ method public void test();
+ }
+
+}
+
package android.net.wifi.p2p {
public class WifiP2pConfig implements android.os.Parcelable {
@@ -22122,6 +22273,7 @@ package android.provider {
field public static final java.lang.String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
field public static final java.lang.String EXTRA_MEDIA_FOCUS = "android.intent.extra.focus";
field public static final java.lang.String EXTRA_MEDIA_GENRE = "android.intent.extra.genre";
+ field public static final java.lang.String EXTRA_MEDIA_PLAYLIST = "android.intent.extra.playlist";
field public static final java.lang.String EXTRA_MEDIA_RADIO_CHANNEL = "android.intent.extra.radio_channel";
field public static final java.lang.String EXTRA_MEDIA_TITLE = "android.intent.extra.title";
field public static final java.lang.String EXTRA_OUTPUT = "output";
@@ -24181,8 +24333,12 @@ package android.service.notification {
ctor public NotificationListenerService();
method public final void cancelAllNotifications();
method public final void cancelNotification(java.lang.String, java.lang.String, int);
+ method public final void cancelNotifications(java.lang.String[]);
+ method public java.lang.String[] getActiveNotificationKeys();
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
+ method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]);
method public android.os.IBinder onBind(android.content.Intent);
+ method public void onListenerConnected(java.lang.String[]);
method public abstract void onNotificationPosted(android.service.notification.StatusBarNotification);
method public abstract void onNotificationRemoved(android.service.notification.StatusBarNotification);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
@@ -24194,6 +24350,7 @@ package android.service.notification {
method public android.service.notification.StatusBarNotification clone();
method public int describeContents();
method public int getId();
+ method public java.lang.String getKey();
method public android.app.Notification getNotification();
method public java.lang.String getPackageName();
method public long getPostTime();
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index cb7e1a0..7c25354 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -14,30 +14,11 @@ LOCAL_SHARED_LIBRARIES := \
libandroid_runtime
LOCAL_MODULE:= app_process
-LOCAL_32_BIT_ONLY := true
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := app_process
+LOCAL_MODULE_STEM_64 := app_process64
include $(BUILD_EXECUTABLE)
-ifeq ($(TARGET_IS_64_BIT),true)
-
-# 64-bit app_process64
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- app_main.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- liblog \
- libbinder \
- libandroid_runtime
-
-LOCAL_MODULE:= app_process64
-LOCAL_NO_2ND_ARCH := true
-include $(BUILD_EXECUTABLE)
-
-endif # TARGET_IS_64_BIT
-
# Build a variant of app_process binary linked with ASan runtime.
# ARM-only at the moment.
ifeq ($(TARGET_ARCH),arm)
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index d513a10..f415c85 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -25,7 +25,7 @@ import android.content.pm.ContainerEncryptionParams;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
@@ -39,6 +39,7 @@ import android.content.pm.VerificationParams;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.Bundle;
import android.os.IUserManager;
import android.os.Process;
import android.os.RemoteException;
@@ -700,14 +701,23 @@ public final class Pm {
ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg);
}
- class PackageInstallObserver extends IPackageInstallObserver.Stub {
+ class PackageInstallObserver extends IPackageInstallObserver2.Stub {
boolean finished;
int result;
+ String extraPermission;
+ String extraPackage;
- public void packageInstalled(String name, int status) {
+ @Override
+ public void packageInstalled(String name, Bundle extras, int status) {
synchronized( this) {
finished = true;
result = status;
+ if (status == PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION) {
+ extraPermission = extras.getString(
+ PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION);
+ extraPackage = extras.getString(
+ PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
+ }
notifyAll();
}
}
@@ -717,7 +727,8 @@ public final class Pm {
* Converts a failure code into a string by using reflection to find a matching constant
* in PackageManager.
*/
- private String installFailureToString(int result) {
+ private String installFailureToString(PackageInstallObserver obs) {
+ final int result = obs.result;
Field[] fields = PackageManager.class.getFields();
for (Field f: fields) {
if (f.getType() == int.class) {
@@ -732,7 +743,16 @@ public final class Pm {
// get the int value and compare it to result.
try {
if (result == f.getInt(null)) {
- return fieldName;
+ StringBuilder sb = new StringBuilder(64);
+ sb.append(fieldName);
+ if (obs.extraPermission != null) {
+ sb.append(" perm=");
+ sb.append(obs.extraPermission);
+ }
+ if (obs.extraPackage != null) {
+ sb.append(" pkg=" + obs.extraPackage);
+ }
+ return sb.toString();
}
} catch (IllegalAccessException e) {
// this shouldn't happen since we only look for public static fields.
@@ -956,7 +976,7 @@ public final class Pm {
VerificationParams verificationParams = new VerificationParams(verificationURI,
originatingURI, referrerURI, VerificationParams.NO_UID, null);
- mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
+ mPm.installPackageWithVerificationAndEncryptionEtc(apkURI, null, obs, installFlags,
installerPackageName, verificationParams, encryptionParams);
synchronized (obs) {
@@ -970,7 +990,7 @@ public final class Pm {
System.out.println("Success");
} else {
System.err.println("Failure ["
- + installFailureToString(obs.result)
+ + installFailureToString(obs)
+ "]");
}
}
diff --git a/core/java/android/animation/RevealAnimator.java b/core/java/android/animation/RevealAnimator.java
new file mode 100644
index 0000000..77a536a
--- /dev/null
+++ b/core/java/android/animation/RevealAnimator.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation;
+
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * Reveals a View with an animated clipping circle.
+ * The clipping is implemented efficiently by talking to a private reveal API on View.
+ * This hidden class currently only accessed by the {@link android.view.View}.
+ *
+ * @hide
+ */
+public class RevealAnimator extends ValueAnimator {
+ private final static String LOGTAG = "RevealAnimator";
+ private ValueAnimator.AnimatorListener mListener;
+ private ValueAnimator.AnimatorUpdateListener mUpdateListener;
+ private RevealCircle mReuseRevealCircle = new RevealCircle(0);
+ private RevealAnimator(final View clipView, final int x, final int y,
+ float startRadius, float endRadius, final boolean inverseClip) {
+
+ setObjectValues(new RevealCircle(startRadius), new RevealCircle(endRadius));
+ setEvaluator(new RevealCircleEvaluator(mReuseRevealCircle));
+
+ mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ RevealCircle circle = (RevealCircle) animation.getAnimatedValue();
+ float radius = circle.getRadius();
+ clipView.setRevealClip(true, inverseClip, x, y, radius);
+ }
+ };
+ mListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ clipView.setRevealClip(false, false, 0, 0, 0);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ clipView.setRevealClip(false, false, 0, 0, 0);
+ }
+ };
+ addUpdateListener(mUpdateListener);
+ addListener(mListener);
+ }
+
+ public static RevealAnimator ofRevealCircle(View clipView, int x, int y,
+ float startRadius, float endRadius, boolean inverseClip) {
+ RevealAnimator anim = new RevealAnimator(clipView, x, y,
+ startRadius, endRadius, inverseClip);
+ return anim;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeAllUpdateListeners() {
+ super.removeAllUpdateListeners();
+ addUpdateListener(mUpdateListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeAllListeners() {
+ super.removeAllListeners();
+ addListener(mListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ArrayList<AnimatorListener> getListeners() {
+ ArrayList<AnimatorListener> allListeners =
+ (ArrayList<AnimatorListener>) super.getListeners().clone();
+ allListeners.remove(mListener);
+ return allListeners;
+ }
+
+ private class RevealCircle {
+ float mRadius;
+
+ public RevealCircle(float radius) {
+ mRadius = radius;
+ }
+
+ public void setRadius(float radius) {
+ mRadius = radius;
+ }
+
+ public float getRadius() {
+ return mRadius;
+ }
+ }
+
+ private class RevealCircleEvaluator implements TypeEvaluator<RevealCircle> {
+
+ private RevealCircle mRevealCircle;
+
+ public RevealCircleEvaluator() {
+ }
+
+ public RevealCircleEvaluator(RevealCircle reuseCircle) {
+ mRevealCircle = reuseCircle;
+ }
+
+ @Override
+ public RevealCircle evaluate(float fraction, RevealCircle startValue,
+ RevealCircle endValue) {
+ float currentRadius = startValue.mRadius
+ + ((endValue.mRadius - startValue.mRadius) * fraction);
+ if (mRevealCircle == null) {
+ return new RevealCircle(currentRadius);
+ } else {
+ mRevealCircle.setRadius(currentRadius);
+ return mRevealCircle;
+ }
+ }
+ }
+}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0615bd9..6ca5244 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -29,6 +29,7 @@ import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
@@ -1073,7 +1074,7 @@ final class ApplicationPackageManager extends PackageManager {
public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
String installerPackageName) {
try {
- mPM.installPackage(packageURI, observer, flags, installerPackageName);
+ mPM.installPackageEtc(packageURI, observer, null, flags, installerPackageName);
} catch (RemoteException e) {
// Should never happen!
}
@@ -1084,8 +1085,8 @@ final class ApplicationPackageManager extends PackageManager {
int flags, String installerPackageName, Uri verificationURI,
ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
try {
- mPM.installPackageWithVerification(packageURI, observer, flags, installerPackageName,
- verificationURI, manifestDigest, encryptionParams);
+ mPM.installPackageWithVerificationEtc(packageURI, observer, null, flags,
+ installerPackageName, verificationURI, manifestDigest, encryptionParams);
} catch (RemoteException e) {
// Should never happen!
}
@@ -1096,8 +1097,46 @@ final class ApplicationPackageManager extends PackageManager {
IPackageInstallObserver observer, int flags, String installerPackageName,
VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
try {
- mPM.installPackageWithVerificationAndEncryption(packageURI, observer, flags,
- installerPackageName, verificationParams, encryptionParams);
+ mPM.installPackageWithVerificationAndEncryptionEtc(packageURI, observer, null,
+ flags, installerPackageName, verificationParams, encryptionParams);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ // Expanded observer-API versions
+ @Override
+ public void installPackage(Uri packageURI, PackageInstallObserver observer,
+ int flags, String installerPackageName) {
+ try {
+ mPM.installPackageEtc(packageURI, null, observer.mObserver,
+ flags, installerPackageName);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ @Override
+ public void installPackageWithVerification(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ Uri verificationURI, ManifestDigest manifestDigest,
+ ContainerEncryptionParams encryptionParams) {
+ try {
+ mPM.installPackageWithVerificationEtc(packageURI, null, observer.mObserver, flags,
+ installerPackageName, verificationURI, manifestDigest, encryptionParams);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ @Override
+ public void installPackageWithVerificationAndEncryption(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ try {
+ mPM.installPackageWithVerificationAndEncryptionEtc(packageURI, null,
+ observer.mObserver, flags, installerPackageName, verificationParams,
+ encryptionParams);
} catch (RemoteException e) {
// Should never happen!
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 589c82f..b2b2571 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -75,6 +75,8 @@ import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot.IWifiHotspotManager;
+import android.net.wifi.hotspot.WifiHotspotManager;
import android.net.wifi.p2p.IWifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager;
import android.nfc.NfcManager;
@@ -552,6 +554,13 @@ class ContextImpl extends Context {
return new WifiManager(ctx.getOuterContext(), service);
}});
+ registerService(WIFI_HOTSPOT_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(WIFI_HOTSPOT_SERVICE);
+ IWifiHotspotManager service = IWifiHotspotManager.Stub.asInterface(b);
+ return new WifiHotspotManager(ctx.getOuterContext(), service);
+ }});
+
registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(WIFI_P2P_SERVICE);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 9f933ca..9911467 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -45,7 +45,8 @@ interface INotificationManager
void unregisterListener(in INotificationListener listener, int userid);
void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id);
- void cancelAllNotificationsFromListener(in INotificationListener token);
+ void cancelNotificationsFromListener(in INotificationListener token, in String[] keys);
- StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token);
+ StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token, in String[] keys);
+ String[] getActiveNotificationKeysFromListener(in INotificationListener token);
} \ No newline at end of file
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 13e74da..36d2635 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -17,12 +17,14 @@
package android.app;
import com.android.internal.R;
+import com.android.internal.util.LegacyNotificationUtil;
import android.annotation.IntDef;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.PorterDuff;
import android.media.AudioManager;
import android.net.Uri;
import android.os.BadParcelableException;
@@ -653,13 +655,6 @@ public class Notification implements Parcelable
public static final String EXTRA_AS_HEADS_UP = "headsup";
/**
- * Extra added from {@link Notification.Builder} to indicate that the remote views were inflated
- * from the builder, as opposed to being created directly from the application.
- * @hide
- */
- public static final String EXTRA_BUILDER_REMOTE_VIEWS = "android.builderRemoteViews";
-
- /**
* Allow certain system-generated notifications to appear before the device is provisioned.
* Only available to notifications coming from the android package.
* @hide
@@ -1315,6 +1310,7 @@ public class Notification implements Parcelable
private int mVisibility = VISIBILITY_PRIVATE;
private Notification mPublicVersion = null;
private boolean mQuantumTheme;
+ private final LegacyNotificationUtil mLegacyNotificationUtil;
/**
* Constructs a new Builder with the defaults:
@@ -1345,6 +1341,10 @@ public class Notification implements Parcelable
// TODO: Decide on targetSdk from calling app whether to use quantum theme.
mQuantumTheme = true;
+
+ // TODO: Decide on targetSdk from calling app whether to instantiate the processor at
+ // all.
+ mLegacyNotificationUtil = LegacyNotificationUtil.getInstance();
}
/**
@@ -1846,42 +1846,50 @@ public class Notification implements Parcelable
boolean showLine3 = false;
boolean showLine2 = false;
int smallIconImageViewId = R.id.icon;
- if (mLargeIcon != null) {
- contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
- smallIconImageViewId = R.id.right_icon;
- }
if (!mQuantumTheme && mPriority < PRIORITY_LOW) {
contentView.setInt(R.id.icon,
"setBackgroundResource", R.drawable.notification_template_icon_low_bg);
contentView.setInt(R.id.status_bar_latest_event_content,
"setBackgroundResource", R.drawable.notification_bg_low);
}
+ if (mLargeIcon != null) {
+ contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
+ processLegacyLargeIcon(mLargeIcon, contentView);
+ smallIconImageViewId = R.id.right_icon;
+ }
if (mSmallIcon != 0) {
contentView.setImageViewResource(smallIconImageViewId, mSmallIcon);
contentView.setViewVisibility(smallIconImageViewId, View.VISIBLE);
+ if (mLargeIcon != null) {
+ processLegacySmallIcon(mSmallIcon, smallIconImageViewId, contentView);
+ } else {
+ processLegacyLargeIcon(mSmallIcon, contentView);
+ }
+
} else {
contentView.setViewVisibility(smallIconImageViewId, View.GONE);
}
if (mContentTitle != null) {
- contentView.setTextViewText(R.id.title, mContentTitle);
+ contentView.setTextViewText(R.id.title, processLegacyText(mContentTitle));
}
if (mContentText != null) {
- contentView.setTextViewText(R.id.text, mContentText);
+ contentView.setTextViewText(R.id.text, processLegacyText(mContentText));
showLine3 = true;
}
if (mContentInfo != null) {
- contentView.setTextViewText(R.id.info, mContentInfo);
+ contentView.setTextViewText(R.id.info, processLegacyText(mContentInfo));
contentView.setViewVisibility(R.id.info, View.VISIBLE);
showLine3 = true;
} else if (mNumber > 0) {
final int tooBig = mContext.getResources().getInteger(
R.integer.status_bar_notification_info_maxnum);
if (mNumber > tooBig) {
- contentView.setTextViewText(R.id.info, mContext.getResources().getString(
- R.string.status_bar_notification_info_overflow));
+ contentView.setTextViewText(R.id.info, processLegacyText(
+ mContext.getResources().getString(
+ R.string.status_bar_notification_info_overflow)));
} else {
NumberFormat f = NumberFormat.getIntegerInstance();
- contentView.setTextViewText(R.id.info, f.format(mNumber));
+ contentView.setTextViewText(R.id.info, processLegacyText(f.format(mNumber)));
}
contentView.setViewVisibility(R.id.info, View.VISIBLE);
showLine3 = true;
@@ -1891,9 +1899,9 @@ public class Notification implements Parcelable
// Need to show three lines?
if (mSubText != null) {
- contentView.setTextViewText(R.id.text, mSubText);
+ contentView.setTextViewText(R.id.text, processLegacyText(mSubText));
if (mContentText != null) {
- contentView.setTextViewText(R.id.text2, mContentText);
+ contentView.setTextViewText(R.id.text2, processLegacyText(mContentText));
contentView.setViewVisibility(R.id.text2, View.VISIBLE);
showLine2 = true;
} else {
@@ -2001,15 +2009,78 @@ public class Notification implements Parcelable
tombstone ? getActionTombstoneLayoutResource()
: getActionLayoutResource());
button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0);
- button.setTextViewText(R.id.action0, action.title);
+ button.setTextViewText(R.id.action0, processLegacyText(action.title));
if (!tombstone) {
button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
}
button.setContentDescription(R.id.action0, action.title);
+ processLegacyAction(action, button);
return button;
}
/**
+ * @return Whether we are currently building a notification from a legacy (an app that
+ * doesn't create quantum notifications by itself) app.
+ */
+ private boolean isLegacy() {
+ return mLegacyNotificationUtil != null;
+ }
+
+ private void processLegacyAction(Action action, RemoteViews button) {
+ if (isLegacy()) {
+ if (mLegacyNotificationUtil.isGrayscale(mContext, action.icon)) {
+ button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0,
+ mContext.getResources().getColor(
+ R.color.notification_action_legacy_color_filter),
+ PorterDuff.Mode.MULTIPLY);
+ }
+ }
+ }
+
+ private CharSequence processLegacyText(CharSequence charSequence) {
+ if (isLegacy()) {
+ return mLegacyNotificationUtil.invertCharSequenceColors(charSequence);
+ } else {
+ return charSequence;
+ }
+ }
+
+ private void processLegacyLargeIcon(int largeIconId, RemoteViews contentView) {
+ if (isLegacy()) {
+ processLegacyLargeIcon(
+ mLegacyNotificationUtil.isGrayscale(mContext, largeIconId),
+ contentView);
+ }
+ }
+
+ private void processLegacyLargeIcon(Bitmap largeIcon, RemoteViews contentView) {
+ if (isLegacy()) {
+ processLegacyLargeIcon(
+ mLegacyNotificationUtil.isGrayscale(largeIcon),
+ contentView);
+ }
+ }
+
+ private void processLegacyLargeIcon(boolean isGrayscale, RemoteViews contentView) {
+ if (isLegacy() && isGrayscale) {
+ contentView.setInt(R.id.icon, "setBackgroundResource",
+ R.drawable.notification_icon_legacy_bg_inset);
+ }
+ }
+
+ private void processLegacySmallIcon(int smallIconDrawableId, int smallIconImageViewId,
+ RemoteViews contentView) {
+ if (isLegacy()) {
+ if (mLegacyNotificationUtil.isGrayscale(mContext, smallIconDrawableId)) {
+ contentView.setDrawableParameters(smallIconImageViewId, false, -1,
+ mContext.getResources().getColor(
+ R.color.notification_action_legacy_color_filter),
+ PorterDuff.Mode.MULTIPLY, -1);
+ }
+ }
+ }
+
+ /**
* Apply the unstyled operations and return a new {@link Notification} object.
* @hide
*/
@@ -2075,7 +2146,6 @@ public class Notification implements Parcelable
extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate);
extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer);
extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen);
- extras.putBoolean(EXTRA_BUILDER_REMOTE_VIEWS, mContentView == null);
if (mLargeIcon != null) {
extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
}
@@ -2226,7 +2296,7 @@ public class Notification implements Parcelable
mSummaryTextSet ? mSummaryText
: mBuilder.mSubText;
if (overflowText != null) {
- contentView.setTextViewText(R.id.text, overflowText);
+ contentView.setTextViewText(R.id.text, mBuilder.processLegacyText(overflowText));
contentView.setViewVisibility(R.id.overflow_divider, View.VISIBLE);
contentView.setViewVisibility(R.id.line3, View.VISIBLE);
} else {
@@ -2437,7 +2507,7 @@ public class Notification implements Parcelable
contentView.setViewPadding(R.id.line1, 0, 0, 0, 0);
}
- contentView.setTextViewText(R.id.big_text, mBigText);
+ contentView.setTextViewText(R.id.big_text, mBuilder.processLegacyText(mBigText));
contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
contentView.setViewVisibility(R.id.text2, View.GONE);
@@ -2542,7 +2612,7 @@ public class Notification implements Parcelable
CharSequence str = mTexts.get(i);
if (str != null && !str.equals("")) {
contentView.setViewVisibility(rowIds[i], View.VISIBLE);
- contentView.setTextViewText(rowIds[i], str);
+ contentView.setTextViewText(rowIds[i], mBuilder.processLegacyText(str));
}
i++;
}
diff --git a/core/java/android/app/PackageInstallObserver.java b/core/java/android/app/PackageInstallObserver.java
new file mode 100644
index 0000000..dacffb4
--- /dev/null
+++ b/core/java/android/app/PackageInstallObserver.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.pm.IPackageInstallObserver2;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+/**
+ * @hide
+ *
+ * New-style observer for package installers to use.
+ */
+public class PackageInstallObserver {
+ IPackageInstallObserver2.Stub mObserver = new IPackageInstallObserver2.Stub() {
+ @Override
+ public void packageInstalled(String pkgName, Bundle extras, int result)
+ throws RemoteException {
+ PackageInstallObserver.this.packageInstalled(pkgName, extras, result);
+ }
+ };
+
+ /**
+ * This method will be called to report the result of the package installation attempt.
+ *
+ * @param pkgName Name of the package whose installation was attempted
+ * @param extras If non-null, this Bundle contains extras providing additional information
+ * about an install failure. See {@link android.content.pm.PackageManager} for
+ * documentation about which extras apply to various failures; in particular the
+ * strings named EXTRA_FAILURE_*.
+ * @param result The numeric success or failure code indicating the basic outcome
+ */
+ public void packageInstalled(String pkgName, Bundle extras, int result) {
+ }
+}
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 66fc816..3074b49 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -52,6 +52,22 @@ public final class DeviceAdminInfo implements Parcelable {
static final String TAG = "DeviceAdminInfo";
/**
+ * A type of policy that this device admin can use: device owner meta-policy
+ * for an admin that is designated as owner of the device.
+ *
+ * @hide
+ */
+ public static final int USES_POLICY_DEVICE_OWNER = -2;
+
+ /**
+ * A type of policy that this device admin can use: profile owner meta-policy
+ * for admins that have been installed as owner of some user profile.
+ *
+ * @hide
+ */
+ public static final int USES_POLICY_PROFILE_OWNER = -1;
+
+ /**
* A type of policy that this device admin can use: limit the passwords
* that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
* and {@link DevicePolicyManager#setPasswordMinimumLength}.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index a4374b8..7b9ced9 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -567,7 +567,7 @@ public final class BluetoothAdapter {
}
/**
- * Stop BLE advertising.
+ * Stop BLE advertising. The callback has to be the same one used for start advertising.
*
* @param callback - {@link AdvertiseCallback}
* @return true if BLE advertising stops, false otherwise.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9f0c384..cd91f3b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1974,6 +1974,7 @@ public abstract class Context {
//@hide: NETWORK_STATS_SERVICE,
//@hide: NETWORK_POLICY_SERVICE,
WIFI_SERVICE,
+ WIFI_HOTSPOT_SERVICE,
WIFI_P2P_SERVICE,
NSD_SERVICE,
AUDIO_SERVICE,
@@ -2324,6 +2325,16 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a {@link
+ * android.net.wifi.hotspot.WifiHotspotManager} for handling management of
+ * Wi-Fi hotspot access.
+ *
+ * @see #getSystemService
+ * @see android.net.wifi.hotspot.WifiHotspotManager
+ */
+ public static final String WIFI_HOTSPOT_SERVICE = "wifihotspot";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a {@link
* android.net.wifi.p2p.WifiP2pManager} for handling management of
* Wi-Fi peer-to-peer connections.
*
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 0175d62..d189a34 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2173,6 +2173,11 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast Action: Wired Headset plugged in or unplugged.
*
+ * You <em>cannot</em> receive this through components declared
+ * in manifests, only by explicitly registering for it with
+ * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
+ * Context.registerReceiver()}.
+ *
* <p>The intent will have the following extra values:
* <ul>
* <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
@@ -2879,6 +2884,14 @@ public class Intent implements Parcelable, Cloneable {
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
public static final String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE";
+ /**
+ * An activity that provides a user interface for adjusting notification preferences for its
+ * containing application. Optional but recommended for apps that post
+ * {@link android.app.Notification Notifications}.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Application launch intent categories (see addCategory()).
diff --git a/core/java/android/content/pm/IPackageInstallObserver2.aidl b/core/java/android/content/pm/IPackageInstallObserver2.aidl
new file mode 100644
index 0000000..2602ab5
--- /dev/null
+++ b/core/java/android/content/pm/IPackageInstallObserver2.aidl
@@ -0,0 +1,45 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content.pm;
+
+import android.os.Bundle;
+
+/**
+ * API for installation callbacks from the Package Manager. In certain result cases
+ * additional information will be provided.
+ * @hide
+ */
+oneway interface IPackageInstallObserver2 {
+ /**
+ * The install operation has completed. {@code returnCode} holds a numeric code
+ * indicating success or failure. In certain cases the {@code extras} Bundle will
+ * contain additional details:
+ *
+ * <p><table>
+ * <tr>
+ * <td>INSTALL_FAILED_DUPLICATE_PERMISSION</td>
+ * <td>Two strings are provided in the extras bundle: EXTRA_EXISTING_PERMISSION
+ * is the name of the permission that the app is attempting to define, and
+ * EXTRA_EXISTING_PACKAGE is the package name of the app which has already
+ * defined the permission.</td>
+ * </tr>
+ * </table>
+ */
+ void packageInstalled(in String packageName, in Bundle extras, int returnCode);
+}
+
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c9fb530..ae0899f 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -25,6 +25,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ContainerEncryptionParams;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageMoveObserver;
@@ -406,6 +407,21 @@ interface IPackageManager {
in VerificationParams verificationParams,
in ContainerEncryptionParams encryptionParams);
+ /** Expanded observer versions */
+ void installPackageEtc(in Uri packageURI, IPackageInstallObserver observer,
+ IPackageInstallObserver2 observer2, int flags, in String installerPackageName);
+
+ void installPackageWithVerificationEtc(in Uri packageURI,
+ in IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+ int flags, in String installerPackageName, in Uri verificationURI,
+ in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams);
+
+ void installPackageWithVerificationAndEncryptionEtc(in Uri packageURI,
+ in IPackageInstallObserver observer, in IPackageInstallObserver2 observer2,
+ int flags, in String installerPackageName,
+ in VerificationParams verificationParams,
+ in ContainerEncryptionParams encryptionParams);
+
int installExistingPackageAsUser(String packageName, int userId);
void verifyPendingInstall(int id, int verificationCode);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e86833b..ceb7764 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -19,6 +19,7 @@ package android.content.pm;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.app.PackageInstallObserver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -683,6 +684,20 @@ public abstract class PackageManager {
public static final int INSTALL_FAILED_USER_RESTRICTED = -111;
/**
+ * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
+ * if the system failed to install the package because it is attempting to define a
+ * permission that is already defined by some existing package.
+ *
+ * <p>The package name of the app which has already defined the permission is passed to
+ * a {@link IPackageInstallObserver2}, if any, as the {@link #EXTRA_EXISTING_PACKAGE}
+ * string extra; and the name of the permission being redefined is passed in the
+ * {@link #EXTRA_EXISTING_PERMISSION} string extra.
+ * @hide
+ */
+ public static final int INSTALL_FAILED_DUPLICATE_PERMISSION = -112;
+
+ /**
* Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
* package's data directory.
*
@@ -1390,6 +1405,24 @@ public abstract class PackageManager {
= "android.content.pm.extra.PERMISSION_LIST";
/**
+ * String extra for {@link IPackageInstallObserver2} in the 'extras' Bundle in case of
+ * {@link #INSTALL_FAILED_DUPLICATE_PERMISSION}. This extra names the package which provides
+ * the existing definition for the permission.
+ * @hide
+ */
+ public static final String EXTRA_FAILURE_EXISTING_PACKAGE
+ = "android.content.pm.extra.FAILURE_EXISTING_PACKAGE";
+
+ /**
+ * String extra for {@link IPackageInstallObserver2} in the 'extras' Bundle in case of
+ * {@link #INSTALL_FAILED_DUPLICATE_PERMISSION}. This extra names the permission that is
+ * being redundantly defined by the package being installed.
+ * @hide
+ */
+ public static final String EXTRA_FAILURE_EXISTING_PERMISSION
+ = "android.content.pm.extra.FAILURE_EXISTING_PERMISSION";
+
+ /**
* Retrieve overall information about an application package that is
* installed on the system.
* <p>
@@ -2752,11 +2785,14 @@ public abstract class PackageManager {
* 'content:' URI.
* @param observer An observer callback to get notified when the package installation is
* complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be
- * called when that happens. observer may be null to indicate that no callback is desired.
+ * called when that happens. This parameter must not be null.
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
* {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
* @param installerPackageName Optional package name of the application that is performing the
* installation. This identifies which market the package came from.
+ * @deprecated Use {@link #installPackage(Uri, IPackageInstallObserver2, int, String)}
+ * instead. This method will continue to be supported but the older observer interface
+ * will not get additional failure details.
*/
public abstract void installPackage(
Uri packageURI, IPackageInstallObserver observer, int flags,
@@ -2772,11 +2808,9 @@ public abstract class PackageManager {
* @param observer An observer callback to get notified when the package
* installation is complete.
* {@link IPackageInstallObserver#packageInstalled(String, int)}
- * will be called when that happens. observer may be null to
- * indicate that no callback is desired.
+ * will be called when that happens. This parameter must not be null.
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}
- * .
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
* @param installerPackageName Optional package name of the application that
* is performing the installation. This identifies which market
* the package came from.
@@ -2789,6 +2823,10 @@ public abstract class PackageManager {
* these parameters describing the encryption and authentication
* used. May be {@code null}.
* @hide
+ * @deprecated Use {@link #installPackageWithVerification(Uri, IPackageInstallObserver2,
+ * int, String, Uri, ManifestDigest, ContainerEncryptionParams)} instead. This method will
+ * continue to be supported but the older observer interface will not get additional failure
+ * details.
*/
public abstract void installPackageWithVerification(Uri packageURI,
IPackageInstallObserver observer, int flags, String installerPackageName,
@@ -2805,11 +2843,9 @@ public abstract class PackageManager {
* @param observer An observer callback to get notified when the package
* installation is complete.
* {@link IPackageInstallObserver#packageInstalled(String, int)}
- * will be called when that happens. observer may be null to
- * indicate that no callback is desired.
+ * will be called when that happens. This parameter must not be null.
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}
- * .
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
* @param installerPackageName Optional package name of the application that
* is performing the installation. This identifies which market
* the package came from.
@@ -2820,12 +2856,101 @@ public abstract class PackageManager {
* used. May be {@code null}.
*
* @hide
+ * @deprecated Use {@link #installPackageWithVerificationAndEncryption(Uri,
+ * IPackageInstallObserver2, int, String, VerificationParams,
+ * ContainerEncryptionParams)} instead. This method will continue to be
+ * supported but the older observer interface will not get additional failure details.
*/
+ @Deprecated
public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
IPackageInstallObserver observer, int flags, String installerPackageName,
VerificationParams verificationParams,
ContainerEncryptionParams encryptionParams);
+ // Package-install variants that take the new, expanded form of observer interface.
+ // Note that these *also* take the original observer type and will redundantly
+ // report the same information to that observer if supplied; but it is not required.
+
+ /**
+ * @hide
+ *
+ * Install a package. Since this may take a little while, the result will
+ * be posted back to the given observer. An installation will fail if the calling context
+ * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
+ * package named in the package file's manifest is already installed, or if there's no space
+ * available on the device.
+ *
+ * @param packageURI The location of the package file to install. This can be a 'file:' or a
+ * 'content:' URI.
+ * @param observer An observer callback to get notified when the package installation is
+ * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
+ * called when that happens. This parameter must not be null.
+ * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
+ * @param installerPackageName Optional package name of the application that is performing the
+ * installation. This identifies which market the package came from.
+ */
+ public abstract void installPackage(
+ Uri packageURI, PackageInstallObserver observer,
+ int flags, String installerPackageName);
+
+ /**
+ * Similar to
+ * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
+ * with an extra verification file provided.
+ *
+ * @param packageURI The location of the package file to install. This can
+ * be a 'file:' or a 'content:' URI.
+ * @param observer An observer callback to get notified when the package installation is
+ * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
+ * called when that happens. This parameter must not be null.
+ * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
+ * @param installerPackageName Optional package name of the application that
+ * is performing the installation. This identifies which market
+ * the package came from.
+ * @param verificationURI The location of the supplementary verification
+ * file. This can be a 'file:' or a 'content:' URI. May be
+ * {@code null}.
+ * @param manifestDigest an object that holds the digest of the package
+ * which can be used to verify ownership. May be {@code null}.
+ * @param encryptionParams if the package to be installed is encrypted,
+ * these parameters describing the encryption and authentication
+ * used. May be {@code null}.
+ * @hide
+ */
+ public abstract void installPackageWithVerification(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ Uri verificationURI, ManifestDigest manifestDigest,
+ ContainerEncryptionParams encryptionParams);
+
+ /**
+ * Similar to
+ * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
+ * with an extra verification information provided.
+ *
+ * @param packageURI The location of the package file to install. This can
+ * be a 'file:' or a 'content:' URI.
+ * @param observer An observer callback to get notified when the package installation is
+ * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
+ * called when that happens. This parameter must not be null.
+ * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
+ * @param installerPackageName Optional package name of the application that
+ * is performing the installation. This identifies which market
+ * the package came from.
+ * @param verificationParams an object that holds signal information to
+ * assist verification. May be {@code null}.
+ * @param encryptionParams if the package to be installed is encrypted,
+ * these parameters describing the encryption and authentication
+ * used. May be {@code null}.
+ *
+ * @hide
+ */
+ public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams);
+
/**
* If there is already an application with the given package name installed
* on the system for other users, also install it for the calling user.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index cf44ad8..a89c507 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1010,13 +1010,14 @@ public class PackageParser {
pkg.mSharedUserLabel = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
}
- sa.recycle();
pkg.installLocation = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_installLocation,
PARSE_DEFAULT_INSTALL_LOCATION);
pkg.applicationInfo.installLocation = pkg.installLocation;
+ sa.recycle();
+
/* Set the global "forward lock" flag */
if ((flags & PARSE_FORWARD_LOCK) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
@@ -1105,7 +1106,6 @@ public class PackageParser {
if (!parseUsesPermission(pkg, res, parser, attrs, outError)) {
return null;
}
-
} else if (tagName.equals("uses-configuration")) {
ConfigurationInfo cPref = new ConfigurationInfo();
sa = res.obtainAttributes(attrs,
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 419abf2..5674154 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -19,6 +19,7 @@ package android.content.res;
import android.graphics.Color;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -181,10 +182,9 @@ public class ColorStateList implements Parcelable {
final int innerDepth = parser.getDepth()+1;
int depth;
- int listAllocated = 20;
+ int[][] stateSpecList = ArrayUtils.newUnpaddedArray(int[].class, 20);
+ int[] colorList = new int[stateSpecList.length];
int listSize = 0;
- int[] colorList = new int[listAllocated];
- int[][] stateSpecList = new int[listAllocated][];
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth=parser.getDepth()) >= innerDepth
@@ -248,21 +248,8 @@ public class ColorStateList implements Parcelable {
mDefaultColor = color;
}
- if (listSize + 1 >= listAllocated) {
- listAllocated = ArrayUtils.idealIntArraySize(listSize + 1);
-
- int[] ncolor = new int[listAllocated];
- System.arraycopy(colorList, 0, ncolor, 0, listSize);
-
- int[][] nstate = new int[listAllocated][];
- System.arraycopy(stateSpecList, 0, nstate, 0, listSize);
-
- colorList = ncolor;
- stateSpecList = nstate;
- }
-
- colorList[listSize] = color;
- stateSpecList[listSize] = stateSpec;
+ colorList = GrowingArrayUtils.append(colorList, listSize, color);
+ stateSpecList = GrowingArrayUtils.append(stateSpecList, listSize, stateSpec);
listSize++;
}
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 9fb2846..15337ce 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -32,7 +32,7 @@ import java.util.Arrays;
* {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
* or {@link Resources#obtainAttributes}. Be
* sure to call {@link #recycle} when done with them.
- *
+ *
* The indices used to retrieve values from this structure correspond to
* the positions of the attributes given to obtainStyledAttributes.
*/
@@ -46,6 +46,7 @@ public class TypedArray {
attrs.mResources = res;
attrs.mMetrics = res.getDisplayMetrics();
attrs.mAssets = res.getAssets();
+ attrs.mRecycled = false;
final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
if (attrs.mData.length >= fullLen) {
@@ -65,6 +66,8 @@ public class TypedArray {
private Resources mResources;
private DisplayMetrics mMetrics;
private AssetManager mAssets;
+ private boolean mRecycled;
+
/*package*/ XmlBlock.Parser mXml;
/*package*/ Resources.Theme mTheme;
/*package*/ int[] mData;
@@ -76,45 +79,65 @@ public class TypedArray {
* Return the number of values in this array.
*/
public int length() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mLength;
}
-
+
/**
* Return the number of indices in the array that actually have data.
*/
public int getIndexCount() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mIndices[0];
}
-
+
/**
* Return an index in the array that has data.
- *
+ *
* @param at The index you would like to returned, ranging from 0 to
* {@link #getIndexCount()}.
- *
+ *
* @return The index at the given offset, which can be used with
* {@link #getValue} and related APIs.
*/
public int getIndex(int at) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mIndices[1+at];
}
-
+
/**
* Return the Resources object this array was loaded from.
*/
public Resources getResources() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mResources;
}
-
+
/**
* Retrieve the styled string value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
- *
- * @return CharSequence holding string data. May be styled. Returns
+ *
+ * @return CharSequence holding string data. May be styled. Returns
* null if the attribute is not defined.
*/
public CharSequence getText(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -136,13 +159,17 @@ public class TypedArray {
/**
* Retrieve the string value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return String holding string data. Any styling information is
* removed. Returns null if the attribute is not defined.
*/
public String getString(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -170,14 +197,18 @@ public class TypedArray {
* attributes, or conversions from other types. As such, this method
* will only return strings for TypedArray objects that come from
* attributes in an XML file.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return String holding string data. Any styling information is
* removed. Returns null if the attribute is not defined or is not
* an immediate string value.
*/
public String getNonResourceString(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -190,12 +221,12 @@ public class TypedArray {
}
return null;
}
-
+
/**
* @hide
* Retrieve the string value for the attribute at <var>index</var> that is
* not allowed to change with the given configurations.
- *
+ *
* @param index Index of attribute to retrieve.
* @param allowedChangingConfigs Bit mask of configurations from
* {@link Configuration}.NATIVE_CONFIG_* that are allowed to change.
@@ -204,6 +235,10 @@ public class TypedArray {
* removed. Returns null if the attribute is not defined.
*/
public String getNonConfigurationString(int index, int allowedChangingConfigs) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -229,13 +264,17 @@ public class TypedArray {
/**
* Retrieve the boolean value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined.
- *
+ *
* @return Attribute boolean value, or defValue if not defined.
*/
public boolean getBoolean(int index, boolean defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -259,13 +298,17 @@ public class TypedArray {
/**
* Retrieve the integer value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined.
- *
+ *
* @return Attribute int value, or defValue if not defined.
*/
public int getInt(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -289,12 +332,16 @@ public class TypedArray {
/**
* Retrieve the float value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return Attribute float value, or defValue if not defined..
*/
public float getFloat(int index, float defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -319,20 +366,24 @@ public class TypedArray {
+ Integer.toHexString(type));
return defValue;
}
-
+
/**
* Retrieve the color value for the attribute at <var>index</var>. If
* the attribute references a color resource holding a complex
* {@link android.content.res.ColorStateList}, then the default color from
* the set is returned.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
+ *
* @return Attribute color value, or defValue if not defined.
*/
public int getColor(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -359,12 +410,16 @@ public class TypedArray {
* Retrieve the ColorStateList for the attribute at <var>index</var>.
* The value may be either a single solid color or a reference to
* a color or complex {@link android.content.res.ColorStateList} description.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return ColorStateList for the attribute, or null if not defined.
*/
public ColorStateList getColorStateList(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
return mResources.loadColorStateList(value, value.resourceId);
@@ -374,14 +429,18 @@ public class TypedArray {
/**
* Retrieve the integer value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
+ *
* @return Attribute integer value, or defValue if not defined.
*/
public int getInteger(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -397,22 +456,26 @@ public class TypedArray {
}
/**
- * Retrieve a dimensional unit attribute at <var>index</var>. Unit
- * conversions are based on the current {@link DisplayMetrics}
- * associated with the resources this {@link TypedArray} object
- * came from.
- *
+ * Retrieve a dimensional unit attribute at <var>index</var>. Unit
+ * conversions are based on the current {@link DisplayMetrics}
+ * associated with the resources this {@link TypedArray} object
+ * came from.
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric, or defValue if not defined.
- *
+ *
* @see #getDimensionPixelOffset
* @see #getDimensionPixelSize
*/
public float getDimension(int index, float defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -433,18 +496,22 @@ public class TypedArray {
* {@link #getDimension}, except the returned value is converted to
* integer pixels for you. An offset conversion involves simply
* truncating the base value to an integer.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels, or defValue if not defined.
- *
+ *
* @see #getDimension
* @see #getDimensionPixelSize
*/
public int getDimensionPixelOffset(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -466,18 +533,22 @@ public class TypedArray {
* integer pixels for use as a size. A size conversion involves
* rounding the base value, and ensuring that a non-zero base value
* is at least one pixel in size.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels, or defValue if not defined.
- *
+ *
* @see #getDimension
* @see #getDimensionPixelOffset
*/
public int getDimensionPixelSize(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -497,14 +568,18 @@ public class TypedArray {
* {@link android.view.ViewGroup}'s layout_width and layout_height
* attributes. This is only here for performance reasons; applications
* should use {@link #getDimensionPixelSize}.
- *
+ *
* @param index Index of the attribute to retrieve.
* @param name Textual name of attribute for error reporting.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels.
*/
public int getLayoutDimension(int index, String name) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -519,21 +594,25 @@ public class TypedArray {
throw new RuntimeException(getPositionDescription()
+ ": You must supply a " + name + " attribute.");
}
-
+
/**
* Special version of {@link #getDimensionPixelSize} for retrieving
* {@link android.view.ViewGroup}'s layout_width and layout_height
* attributes. This is only here for performance reasons; applications
* should use {@link #getDimensionPixelSize}.
- *
+ *
* @param index Index of the attribute to retrieve.
* @param defValue The default value to return if this attribute is not
* default or contains the wrong type of data.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels.
*/
public int getLayoutDimension(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -550,20 +629,24 @@ public class TypedArray {
/**
* Retrieve a fractional unit attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param base The base value of this fraction. In other words, a
+ *
+ * @param index Index of attribute to retrieve.
+ * @param base The base value of this fraction. In other words, a
* standard fraction is multiplied by this value.
- * @param pbase The parent base value of this fraction. In other
+ * @param pbase The parent base value of this fraction. In other
* words, a parent fraction (nn%p) is multiplied by this
* value.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
- * @return Attribute fractional value multiplied by the appropriate
- * base value, or defValue if not defined.
+ *
+ * @return Attribute fractional value multiplied by the appropriate
+ * base value, or defValue if not defined.
*/
public float getFraction(int index, int base, int pbase, float defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -580,19 +663,23 @@ public class TypedArray {
/**
* Retrieve the resource identifier for the attribute at
- * <var>index</var>. Note that attribute resource as resolved when
- * the overall {@link TypedArray} object is retrieved. As a
- * result, this function will return the resource identifier of the
- * final resource value that was found, <em>not</em> necessarily the
- * original resource that was specified by the attribute.
- *
+ * <var>index</var>. Note that attribute resource as resolved when
+ * the overall {@link TypedArray} object is retrieved. As a
+ * result, this function will return the resource identifier of the
+ * final resource value that was found, <em>not</em> necessarily the
+ * original resource that was specified by the attribute.
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
+ *
* @return Attribute resource identifier, or defValue if not defined.
*/
public int getResourceId(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
@@ -615,6 +702,10 @@ public class TypedArray {
* @hide
*/
public int getThemeAttributeId(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
if (data[index + AssetManager.STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
@@ -628,12 +719,16 @@ public class TypedArray {
* gets the resource ID of the selected attribute, and uses
* {@link Resources#getDrawable Resources.getDrawable} of the owning
* Resources object to retrieve its Drawable.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return Drawable for the attribute, or null if not defined.
*/
public Drawable getDrawable(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (false) {
@@ -655,12 +750,16 @@ public class TypedArray {
* This gets the resource ID of the selected attribute, and uses
* {@link Resources#getTextArray Resources.getTextArray} of the owning
* Resources object to retrieve its String[].
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return CharSequence[] for the attribute, or null if not defined.
*/
public CharSequence[] getTextArray(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (false) {
@@ -679,36 +778,19 @@ public class TypedArray {
/**
* Retrieve the raw TypedValue for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
* @param outValue TypedValue object in which to place the attribute's
* data.
- *
- * @return Returns true if the value was retrieved, else false.
- */
- public boolean getValue(int index, TypedValue outValue) {
- return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
- }
-
- /**
- * Determines whether this TypedArray contains an attribute of the specified
- * type.
*
- * @param type Type of data, e.g. {@link TypedValue#TYPE_ATTRIBUTE}
- * @return True if the TypedArray contains an attribute of the specified
- * type.
- * @hide
+ * @return Returns true if the value was retrieved, else false.
*/
- public boolean hasType(int type) {
- final int[] data = mData;
- final int N = getIndexCount();
- for (int i = 0; i < N; i++) {
- final int index = getIndex(i) * AssetManager.STYLE_NUM_ENTRIES;
- if (data[index + AssetManager.STYLE_TYPE] == type) {
- return true;
- }
+ public boolean getValue(int index, TypedValue outValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- return false;
+
+ return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
}
/**
@@ -718,36 +800,48 @@ public class TypedArray {
* @return Attribute type.
*/
public int getType(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
return mData[index + AssetManager.STYLE_TYPE];
}
/**
* Determines whether there is an attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return True if the attribute has a value, false otherwise.
*/
public boolean hasValue(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
return type != TypedValue.TYPE_NULL;
}
-
+
/**
- * Retrieve the raw TypedValue for the attribute at <var>index</var>
- * and return a temporary object holding its data. This object is only
- * valid until the next call on to {@link TypedArray}.
- *
+ * Retrieve the raw TypedValue for the attribute at <var>index</var>
+ * and return a temporary object holding its data. This object is only
+ * valid until the next call on to {@link TypedArray}.
+ *
* @param index Index of attribute to retrieve.
- *
- * @return Returns a TypedValue object if the attribute is defined,
+ *
+ * @return Returns a TypedValue object if the attribute is defined,
* containing its data; otherwise returns null. (You will not
* receive a TypedValue whose type is TYPE_NULL.)
*/
public TypedValue peekValue(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
return value;
@@ -759,13 +853,23 @@ public class TypedArray {
* Returns a message about the parser state suitable for printing error messages.
*/
public String getPositionDescription() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mXml != null ? mXml.getPositionDescription() : "<internal>";
}
/**
- * Give back a previously retrieved array, for later re-use.
+ * Recycle the TypedArray, to be re-used by a later caller. After calling
+ * this function you must not ever touch the typed array again.
*/
public void recycle() {
+ if (mRecycled) {
+ throw new RuntimeException(toString() + " recycled twice!");
+ }
+
+ mRecycled = true;
mResources = null;
mMetrics = null;
mAssets = null;
@@ -791,6 +895,10 @@ public class TypedArray {
* @hide
*/
public int[] extractThemeAttrs() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
int[] attrs = null;
final int N = length();
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 37bead8..ff77580 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1093,8 +1093,8 @@ public final class CameraCharacteristics extends CameraMetadata {
*
* @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
*/
- public static final Key<Byte> SENSOR_AVAILABLE_TEST_PATTERN_MODES =
- new Key<Byte>("android.sensor.availableTestPatternModes", byte.class);
+ public static final Key<int[]> SENSOR_AVAILABLE_TEST_PATTERN_MODES =
+ new Key<int[]>("android.sensor.availableTestPatternModes", int[].class);
/**
* <p>Which face detection modes are available,
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 42c8e3d..679310a 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1002,8 +1002,11 @@ public abstract class CameraMetadata {
* controls; the camera device will ignore those settings while
* USE_SCENE_MODE is active (except for FACE_PRIORITY
* scene mode). Other control entries are still active.
- * This setting can only be used if availableSceneModes !=
- * UNSUPPORTED</p>
+ * This setting can only be used if scene mode is supported
+ * (i.e. {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes} contain some modes
+ * other than DISABLED).</p>
+ *
+ * @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
* @see CaptureRequest#CONTROL_MODE
*/
public static final int CONTROL_MODE_USE_SCENE_MODE = 2;
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
index a28b5a7..d06355d 100644
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ b/core/java/android/net/http/CertificateChainValidator.java
@@ -22,6 +22,8 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
@@ -74,13 +76,16 @@ public class CertificateChainValidator {
private CertificateChainValidator() {
try {
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509");
+ tmf.init((KeyStore) null);
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509ExtendedTrustManager) {
mTrustManager = (X509ExtendedTrustManager) tm;
}
}
} catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("X.509 TrustManager factory must be available", e);
+ throw new RuntimeException("X.509 TrustManagerFactory must be available", e);
+ } catch (KeyStoreException e) {
+ throw new RuntimeException("X.509 TrustManagerFactory cannot be initialized", e);
}
if (mTrustManager == null) {
@@ -166,9 +171,13 @@ public class CertificateChainValidator {
TrustManagerFactory tmf;
try {
tmf = TrustManagerFactory.getInstance("X.509");
+ tmf.init((KeyStore) null);
} catch (NoSuchAlgorithmException e) {
Slog.w(TAG, "Couldn't find default X.509 TrustManagerFactory");
return;
+ } catch (KeyStoreException e) {
+ Slog.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e);
+ return;
}
TrustManager[] tms = tmf.getTrustManagers();
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index bd576af..ae24968 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -173,6 +173,10 @@ public final class MediaStore {
*/
public static final String EXTRA_MEDIA_GENRE = "android.intent.extra.genre";
/**
+ * The name of the Intent-extra used to define the playlist.
+ */
+ public static final String EXTRA_MEDIA_PLAYLIST = "android.intent.extra.playlist";
+ /**
* The name of the Intent-extra used to define the radio channel.
*/
public static final String EXTRA_MEDIA_RADIO_CHANNEL = "android.intent.extra.radio_channel";
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 425fdc1..d4b29d8 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -21,6 +21,7 @@ import android.service.notification.StatusBarNotification;
/** @hide */
oneway interface INotificationListener
{
+ void onListenerConnected(in String[] notificationKeys);
void onNotificationPosted(in StatusBarNotification notification);
void onNotificationRemoved(in StatusBarNotification notification);
} \ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index cf862b8..050e1a0 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -83,6 +83,17 @@ public abstract class NotificationListenerService extends Service {
*/
public abstract void onNotificationRemoved(StatusBarNotification sbn);
+ /**
+ * Implement this method to learn about when the listener is enabled and connected to
+ * the notification manager. You are safe to call {@link #getActiveNotifications(String[])
+ * at this time.
+ *
+ * @param notificationKeys The notification keys for all currently posted notifications.
+ */
+ public void onListenerConnected(String[] notificationKeys) {
+ // optional
+ }
+
private final INotificationManager getNotificationInterface() {
if (mNoMan == null) {
mNoMan = INotificationManager.Stub.asInterface(
@@ -132,9 +143,23 @@ public abstract class NotificationListenerService extends Service {
* {@see #cancelNotification(String, String, int)}
*/
public final void cancelAllNotifications() {
+ cancelNotifications(null /*all*/);
+ }
+
+ /**
+ * Inform the notification manager about dismissal of specific notifications.
+ * <p>
+ * Use this if your listener has a user interface that allows the user to dismiss
+ * multiple notifications at once.
+ *
+ * @param keys Notifications to dismiss, or {@code null} to dismiss all.
+ *
+ * {@see #cancelNotification(String, String, int)}
+ */
+ public final void cancelNotifications(String[] keys) {
if (!isBound()) return;
try {
- getNotificationInterface().cancelAllNotificationsFromListener(mWrapper);
+ getNotificationInterface().cancelNotificationsFromListener(mWrapper, keys);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -142,14 +167,43 @@ public abstract class NotificationListenerService extends Service {
/**
* Request the list of outstanding notifications (that is, those that are visible to the
- * current user). Useful when starting up and you don't know what's already been posted.
+ * current user). Useful when you don't know what's already been posted.
*
* @return An array of active notifications.
*/
public StatusBarNotification[] getActiveNotifications() {
+ return getActiveNotifications(null /*all*/);
+ }
+
+ /**
+ * Request the list of outstanding notifications (that is, those that are visible to the
+ * current user). Useful when you don't know what's already been posted.
+ *
+ * @param keys A specific list of notification keys, or {@code null} for all.
+ * @return An array of active notifications.
+ */
+ public StatusBarNotification[] getActiveNotifications(String[] keys) {
+ if (!isBound()) return null;
+ try {
+ return getNotificationInterface().getActiveNotificationsFromListener(mWrapper, keys);
+ } catch (android.os.RemoteException ex) {
+ Log.v(TAG, "Unable to contact notification manager", ex);
+ }
+ return null;
+ }
+
+ /**
+ * Request the list of outstanding notification keys(that is, those that are visible to the
+ * current user). You can use the notification keys for subsequent retrieval via
+ * {@link #getActiveNotifications(String[]) or dismissal via
+ * {@link #cancelNotifications(String[]).
+ *
+ * @return An array of active notification keys.
+ */
+ public String[] getActiveNotificationKeys() {
if (!isBound()) return null;
try {
- return getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
+ return getNotificationInterface().getActiveNotificationKeysFromListener(mWrapper);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -189,5 +243,13 @@ public abstract class NotificationListenerService extends Service {
Log.w(TAG, "Error running onNotificationRemoved", t);
}
}
+ @Override
+ public void onListenerConnected(String[] notificationKeys) {
+ try {
+ NotificationListenerService.this.onListenerConnected(notificationKeys);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onListenerConnected", t);
+ }
+ }
}
}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index b5b9e14..7f15ab8 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -29,6 +29,7 @@ public class StatusBarNotification implements Parcelable {
private final String pkg;
private final int id;
private final String tag;
+ private final String key;
private final int uid;
private final String basePkg;
@@ -68,8 +69,8 @@ public class StatusBarNotification implements Parcelable {
this.notification = notification;
this.user = user;
this.notification.setUser(user);
-
this.postTime = postTime;
+ this.key = key();
}
public StatusBarNotification(Parcel in) {
@@ -88,6 +89,11 @@ public class StatusBarNotification implements Parcelable {
this.user = UserHandle.readFromParcel(in);
this.notification.setUser(this.user);
this.postTime = in.readLong();
+ this.key = key();
+ }
+
+ private String key() {
+ return pkg + '|' + basePkg + '|' + id + '|' + tag + '|' + uid;
}
public void writeToParcel(Parcel out, int flags) {
@@ -148,9 +154,9 @@ public class StatusBarNotification implements Parcelable {
@Override
public String toString() {
return String.format(
- "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d: %s)",
+ "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
this.pkg, this.user, this.id, this.tag,
- this.score, this.notification);
+ this.score, this.key, this.notification);
}
/** Convenience method to check the notification's flags for
@@ -230,4 +236,11 @@ public class StatusBarNotification implements Parcelable {
public int getScore() {
return score;
}
+
+ /**
+ * A unique instance key for this notification record.
+ */
+ public String getKey() {
+ return key;
+ }
}
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 06935ae..77ef1da 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -21,6 +21,7 @@ import android.text.style.UpdateLayout;
import android.text.style.WrapTogetherSpan;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import java.lang.ref.WeakReference;
@@ -401,7 +402,7 @@ public class DynamicLayout extends Layout
if (mBlockEndLines == null) {
// Initial creation of the array, no test on previous block ending line
- mBlockEndLines = new int[ArrayUtils.idealIntArraySize(1)];
+ mBlockEndLines = ArrayUtils.newUnpaddedIntArray(1);
mBlockEndLines[mNumberOfBlocks] = line;
mNumberOfBlocks++;
return;
@@ -409,13 +410,7 @@ public class DynamicLayout extends Layout
final int previousBlockEndLine = mBlockEndLines[mNumberOfBlocks - 1];
if (line > previousBlockEndLine) {
- if (mNumberOfBlocks == mBlockEndLines.length) {
- // Grow the array if needed
- int[] blockEndLines = new int[ArrayUtils.idealIntArraySize(mNumberOfBlocks + 1)];
- System.arraycopy(mBlockEndLines, 0, blockEndLines, 0, mNumberOfBlocks);
- mBlockEndLines = blockEndLines;
- }
- mBlockEndLines[mNumberOfBlocks] = line;
+ mBlockEndLines = GrowingArrayUtils.append(mBlockEndLines, mNumberOfBlocks, line);
mNumberOfBlocks++;
}
}
@@ -483,9 +478,9 @@ public class DynamicLayout extends Layout
}
if (newNumberOfBlocks > mBlockEndLines.length) {
- final int newSize = ArrayUtils.idealIntArraySize(newNumberOfBlocks);
- int[] blockEndLines = new int[newSize];
- int[] blockIndices = new int[newSize];
+ int[] blockEndLines = ArrayUtils.newUnpaddedIntArray(
+ Math.max(mBlockEndLines.length * 2, newNumberOfBlocks));
+ int[] blockIndices = new int[blockEndLines.length];
System.arraycopy(mBlockEndLines, 0, blockEndLines, 0, firstBlock);
System.arraycopy(mBlockIndices, 0, blockIndices, 0, firstBlock);
System.arraycopy(mBlockEndLines, lastBlock + 1,
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index c80321c..2fcc597 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -211,7 +211,7 @@ public class Html {
private static String getOpenParaTagWithDirection(Spanned text, int start, int end) {
final int len = end - start;
- final byte[] levels = new byte[ArrayUtils.idealByteArraySize(len)];
+ final byte[] levels = ArrayUtils.newUnpaddedByteArray(len);
final char[] buffer = TextUtils.obtain(len);
TextUtils.getChars(text, start, end, buffer, 0);
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 9dfd383..4bfcaff 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -31,6 +31,7 @@ import android.text.style.ReplacementSpan;
import android.text.style.TabStopSpan;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import java.util.Arrays;
@@ -403,14 +404,9 @@ public abstract class Layout {
// construction
if (mLineBackgroundSpans.spanStarts[j] >= end ||
mLineBackgroundSpans.spanEnds[j] <= start) continue;
- if (spansLength == spans.length) {
- // The spans array needs to be expanded
- int newSize = ArrayUtils.idealObjectArraySize(2 * spansLength);
- ParagraphStyle[] newSpans = new ParagraphStyle[newSize];
- System.arraycopy(spans, 0, newSpans, 0, spansLength);
- spans = newSpans;
- }
- spans[spansLength++] = mLineBackgroundSpans.spans[j];
+ spans = GrowingArrayUtils.append(
+ spans, spansLength, mLineBackgroundSpans.spans[j]);
+ spansLength++;
}
}
}
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index 101d6a2..f8e3c83 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -98,10 +98,10 @@ class MeasuredText {
mPos = 0;
if (mWidths == null || mWidths.length < len) {
- mWidths = new float[ArrayUtils.idealFloatArraySize(len)];
+ mWidths = ArrayUtils.newUnpaddedFloatArray(len);
}
if (mChars == null || mChars.length < len) {
- mChars = new char[ArrayUtils.idealCharArraySize(len)];
+ mChars = ArrayUtils.newUnpaddedCharArray(len);
}
TextUtils.getChars(text, start, end, mChars, 0);
@@ -130,7 +130,7 @@ class MeasuredText {
mEasy = true;
} else {
if (mLevels == null || mLevels.length < len) {
- mLevels = new byte[ArrayUtils.idealByteArraySize(len)];
+ mLevels = ArrayUtils.newUnpaddedByteArray(len);
}
int bidiRequest;
if (textDir == TextDirectionHeuristics.LTR) {
diff --git a/core/java/android/text/PackedIntVector.java b/core/java/android/text/PackedIntVector.java
index d87f600..546ab44 100644
--- a/core/java/android/text/PackedIntVector.java
+++ b/core/java/android/text/PackedIntVector.java
@@ -17,6 +17,7 @@
package android.text;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
/**
@@ -252,9 +253,9 @@ class PackedIntVector {
*/
private final void growBuffer() {
final int columns = mColumns;
- int newsize = size() + 1;
- newsize = ArrayUtils.idealIntArraySize(newsize * columns) / columns;
- int[] newvalues = new int[newsize * columns];
+ int[] newvalues = ArrayUtils.newUnpaddedIntArray(
+ GrowingArrayUtils.growSize(size()) * columns);
+ int newsize = newvalues.length / columns;
final int[] valuegap = mValueGap;
final int rowgapstart = mRowGapStart;
diff --git a/core/java/android/text/PackedObjectVector.java b/core/java/android/text/PackedObjectVector.java
index a29df09..b777e16 100644
--- a/core/java/android/text/PackedObjectVector.java
+++ b/core/java/android/text/PackedObjectVector.java
@@ -17,6 +17,9 @@
package android.text;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
class PackedObjectVector<E>
{
@@ -32,12 +35,11 @@ class PackedObjectVector<E>
PackedObjectVector(int columns)
{
mColumns = columns;
- mRows = ArrayUtils.idealIntArraySize(0) / mColumns;
+ mValues = EmptyArray.OBJECT;
+ mRows = 0;
mRowGapStart = 0;
mRowGapLength = mRows;
-
- mValues = new Object[mRows * mColumns];
}
public E
@@ -109,10 +111,9 @@ class PackedObjectVector<E>
private void
growBuffer()
{
- int newsize = size() + 1;
- newsize = ArrayUtils.idealIntArraySize(newsize * mColumns) / mColumns;
- Object[] newvalues = new Object[newsize * mColumns];
-
+ Object[] newvalues = ArrayUtils.newUnpaddedObjectArray(
+ GrowingArrayUtils.growSize(size()) * mColumns);
+ int newsize = newvalues.length / mColumns;
int after = mRows - (mRowGapStart + mRowGapLength);
System.arraycopy(mValues, 0, newvalues, 0, mColumns * mRowGapStart);
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index b55cd6a..f440853 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -21,6 +21,9 @@ import android.graphics.Paint;
import android.util.Log;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
import java.lang.reflect.Array;
@@ -54,19 +57,17 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
if (srclen < 0) throw new StringIndexOutOfBoundsException();
- int len = ArrayUtils.idealCharArraySize(srclen + 1);
- mText = new char[len];
+ mText = ArrayUtils.newUnpaddedCharArray(GrowingArrayUtils.growSize(srclen));
mGapStart = srclen;
- mGapLength = len - srclen;
+ mGapLength = mText.length - srclen;
TextUtils.getChars(text, start, end, mText, 0);
mSpanCount = 0;
- int alloc = ArrayUtils.idealIntArraySize(0);
- mSpans = new Object[alloc];
- mSpanStarts = new int[alloc];
- mSpanEnds = new int[alloc];
- mSpanFlags = new int[alloc];
+ mSpans = EmptyArray.OBJECT;
+ mSpanStarts = EmptyArray.INT;
+ mSpanEnds = EmptyArray.INT;
+ mSpanFlags = EmptyArray.INT;
if (text instanceof Spanned) {
Spanned sp = (Spanned) text;
@@ -130,12 +131,14 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
private void resizeFor(int size) {
final int oldLength = mText.length;
- final int newLength = ArrayUtils.idealCharArraySize(size + 1);
- final int delta = newLength - oldLength;
- if (delta == 0) return;
+ if (size + 1 <= oldLength) {
+ return;
+ }
- char[] newText = new char[newLength];
+ char[] newText = ArrayUtils.newUnpaddedCharArray(GrowingArrayUtils.growSize(size));
System.arraycopy(mText, 0, newText, 0, mGapStart);
+ final int newLength = newText.length;
+ final int delta = newLength - oldLength;
final int after = oldLength - (mGapStart + mGapLength);
System.arraycopy(mText, oldLength - after, newText, newLength - after, after);
mText = newText;
@@ -679,28 +682,10 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
}
}
- if (mSpanCount + 1 >= mSpans.length) {
- int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1);
- Object[] newspans = new Object[newsize];
- int[] newspanstarts = new int[newsize];
- int[] newspanends = new int[newsize];
- int[] newspanflags = new int[newsize];
-
- System.arraycopy(mSpans, 0, newspans, 0, mSpanCount);
- System.arraycopy(mSpanStarts, 0, newspanstarts, 0, mSpanCount);
- System.arraycopy(mSpanEnds, 0, newspanends, 0, mSpanCount);
- System.arraycopy(mSpanFlags, 0, newspanflags, 0, mSpanCount);
-
- mSpans = newspans;
- mSpanStarts = newspanstarts;
- mSpanEnds = newspanends;
- mSpanFlags = newspanflags;
- }
-
- mSpans[mSpanCount] = what;
- mSpanStarts[mSpanCount] = start;
- mSpanEnds[mSpanCount] = end;
- mSpanFlags[mSpanCount] = flags;
+ mSpans = GrowingArrayUtils.append(mSpans, mSpanCount, what);
+ mSpanStarts = GrowingArrayUtils.append(mSpanStarts, mSpanCount, start);
+ mSpanEnds = GrowingArrayUtils.append(mSpanEnds, mSpanCount, end);
+ mSpanFlags = GrowingArrayUtils.append(mSpanFlags, mSpanCount, flags);
mSpanCount++;
if (send) sendSpanAdded(what, nstart, nend);
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 456a3e5..d114d32 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -17,6 +17,9 @@
package android.text;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
import java.lang.reflect.Array;
@@ -29,9 +32,8 @@ import java.lang.reflect.Array;
else
mText = source.toString().substring(start, end);
- int initial = ArrayUtils.idealIntArraySize(0);
- mSpans = new Object[initial];
- mSpanData = new int[initial * 3];
+ mSpans = EmptyArray.OBJECT;
+ mSpanData = EmptyArray.INT;
if (source instanceof Spanned) {
Spanned sp = (Spanned) source;
@@ -115,9 +117,9 @@ import java.lang.reflect.Array;
}
if (mSpanCount + 1 >= mSpans.length) {
- int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1);
- Object[] newtags = new Object[newsize];
- int[] newdata = new int[newsize * 3];
+ Object[] newtags = ArrayUtils.newUnpaddedObjectArray(
+ GrowingArrayUtils.growSize(mSpanCount));
+ int[] newdata = new int[newtags.length * 3];
System.arraycopy(mSpans, 0, newtags, 0, mSpanCount);
System.arraycopy(mSpanData, 0, newdata, 0, mSpanCount * 3);
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index e7d6fda..535eee1 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -26,6 +26,7 @@ import android.text.style.TabStopSpan;
import android.util.Log;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
/**
* StaticLayout is a Layout for text that will not be edited after it
@@ -130,9 +131,8 @@ public class StaticLayout extends Layout {
mEllipsizedWidth = outerwidth;
}
- mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
- mLineDirections = new Directions[
- ArrayUtils.idealIntArraySize(2 * mColumns)];
+ mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2 * mColumns);
+ mLines = new int[mLineDirections.length];
mMaximumVisibleLineCount = maxLines;
mMeasured = MeasuredText.obtain();
@@ -149,8 +149,8 @@ public class StaticLayout extends Layout {
super(text, null, 0, null, 0, 0);
mColumns = COLUMNS_ELLIPSIZE;
- mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
- mLineDirections = new Directions[ArrayUtils.idealIntArraySize(2 * mColumns)];
+ mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2 * mColumns);
+ mLines = new int[mLineDirections.length];
// FIXME This is never recycled
mMeasured = MeasuredText.obtain();
}
@@ -215,8 +215,7 @@ public class StaticLayout extends Layout {
if (chooseHt.length != 0) {
if (chooseHtv == null ||
chooseHtv.length < chooseHt.length) {
- chooseHtv = new int[ArrayUtils.idealIntArraySize(
- chooseHt.length)];
+ chooseHtv = ArrayUtils.newUnpaddedIntArray(chooseHt.length);
}
for (int i = 0; i < chooseHt.length; i++) {
@@ -599,16 +598,16 @@ public class StaticLayout extends Layout {
int[] lines = mLines;
if (want >= lines.length) {
- int nlen = ArrayUtils.idealIntArraySize(want + 1);
- int[] grow = new int[nlen];
- System.arraycopy(lines, 0, grow, 0, lines.length);
- mLines = grow;
- lines = grow;
-
- Directions[] grow2 = new Directions[nlen];
+ Directions[] grow2 = ArrayUtils.newUnpaddedArray(
+ Directions.class, GrowingArrayUtils.growSize(want));
System.arraycopy(mLineDirections, 0, grow2, 0,
mLineDirections.length);
mLineDirections = grow2;
+
+ int[] grow = new int[grow2.length];
+ System.arraycopy(lines, 0, grow, 0, lines.length);
+ mLines = grow;
+ lines = grow;
}
if (chooseHt != null) {
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 1fecf81..d892f19 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -153,7 +153,7 @@ class TextLine {
if (mCharsValid) {
if (mChars == null || mChars.length < mLen) {
- mChars = new char[ArrayUtils.idealCharArraySize(mLen)];
+ mChars = ArrayUtils.newUnpaddedCharArray(mLen);
}
TextUtils.getChars(text, start, limit, mChars, 0);
if (hasReplacement) {
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 596ca8c..f06ae71 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1321,7 +1321,7 @@ public class TextUtils {
}
if (buf == null || buf.length < len)
- buf = new char[ArrayUtils.idealCharArraySize(len)];
+ buf = ArrayUtils.newUnpaddedCharArray(len);
return buf;
}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index df1d4cd..9a0b7fc 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -16,6 +16,8 @@
package android.util;
+import libcore.util.EmptyArray;
+
import java.util.Collection;
import java.util.Map;
import java.util.Set;
@@ -234,8 +236,8 @@ public final class ArrayMap<K, V> implements Map<K, V> {
* will grow once items are added to it.
*/
public ArrayMap() {
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
@@ -244,8 +246,8 @@ public final class ArrayMap<K, V> implements Map<K, V> {
*/
public ArrayMap(int capacity) {
if (capacity == 0) {
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
} else {
allocArrays(capacity);
}
@@ -253,8 +255,8 @@ public final class ArrayMap<K, V> implements Map<K, V> {
}
private ArrayMap(boolean immutable) {
- mHashes = EMPTY_IMMUTABLE_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
@@ -275,8 +277,8 @@ public final class ArrayMap<K, V> implements Map<K, V> {
public void clear() {
if (mSize > 0) {
freeArrays(mHashes, mArray, mSize);
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
}
@@ -540,8 +542,8 @@ public final class ArrayMap<K, V> implements Map<K, V> {
// Now empty.
if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0");
freeArrays(mHashes, mArray, mSize);
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
} else {
if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) {
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 3c695e9..9d4b720 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -16,6 +16,8 @@
package android.util;
+import libcore.util.EmptyArray;
+
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
@@ -222,8 +224,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
* will grow once items are added to it.
*/
public ArraySet() {
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
@@ -232,8 +234,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
*/
public ArraySet(int capacity) {
if (capacity == 0) {
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
} else {
allocArrays(capacity);
}
@@ -258,8 +260,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
public void clear() {
if (mSize != 0) {
freeArrays(mHashes, mArray, mSize);
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
}
@@ -413,8 +415,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
// Now empty.
if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0");
freeArrays(mHashes, mArray, mSize);
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
} else {
if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) {
diff --git a/core/java/android/util/ContainerHelpers.java b/core/java/android/util/ContainerHelpers.java
index 624c4bd..4e5fefb 100644
--- a/core/java/android/util/ContainerHelpers.java
+++ b/core/java/android/util/ContainerHelpers.java
@@ -17,10 +17,6 @@
package android.util;
class ContainerHelpers {
- static final boolean[] EMPTY_BOOLEANS = new boolean[0];
- static final int[] EMPTY_INTS = new int[0];
- static final long[] EMPTY_LONGS = new long[0];
- static final Object[] EMPTY_OBJECTS = new Object[0];
// This is Arrays.binarySearch(), but doesn't do any argument validation.
static int binarySearch(int[] array, int size, int value) {
diff --git a/core/java/android/util/LongArray.java b/core/java/android/util/LongArray.java
index d5f15f0..54a6882 100644
--- a/core/java/android/util/LongArray.java
+++ b/core/java/android/util/LongArray.java
@@ -17,6 +17,7 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import libcore.util.EmptyArray;
/**
* Implements a growing array of long primitives.
@@ -41,10 +42,9 @@ public class LongArray implements Cloneable {
*/
public LongArray(int initialCapacity) {
if (initialCapacity == 0) {
- mValues = ContainerHelpers.EMPTY_LONGS;
+ mValues = EmptyArray.LONG;
} else {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
- mValues = new long[initialCapacity];
+ mValues = ArrayUtils.newUnpaddedLongArray(initialCapacity);
}
mSize = 0;
}
@@ -97,7 +97,7 @@ public class LongArray implements Cloneable {
final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : currentSize >> 1);
final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity;
- final long[] newValues = new long[ArrayUtils.idealLongArraySize(newCapacity)];
+ final long[] newValues = ArrayUtils.newUnpaddedLongArray(newCapacity);
System.arraycopy(mValues, 0, newValues, 0, currentSize);
mValues = newValues;
}
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index dab853a..6b45ff4 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseArray mapping longs to Objects. Unlike a normal array of Objects,
@@ -70,12 +73,11 @@ public class LongSparseArray<E> implements Cloneable {
*/
public LongSparseArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_LONGS;
- mValues = ContainerHelpers.EMPTY_OBJECTS;
+ mKeys = EmptyArray.LONG;
+ mValues = EmptyArray.OBJECT;
} else {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
- mKeys = new long[initialCapacity];
- mValues = new Object[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedLongArray(initialCapacity);
+ mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);
}
mSize = 0;
}
@@ -202,28 +204,8 @@ public class LongSparseArray<E> implements Cloneable {
i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
}
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealLongArraySize(mSize + 1);
-
- long[] nkeys = new long[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -353,24 +335,9 @@ public class LongSparseArray<E> implements Cloneable {
gc();
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealLongArraySize(pos + 1);
-
- long[] nkeys = new long[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index b8073dd..a361457 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* Map of {@code long} to {@code long}. Unlike a normal array of longs, there
@@ -62,12 +65,11 @@ public class LongSparseLongArray implements Cloneable {
*/
public LongSparseLongArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_LONGS;
- mValues = ContainerHelpers.EMPTY_LONGS;
+ mKeys = EmptyArray.LONG;
+ mValues = EmptyArray.LONG;
} else {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
- mKeys = new long[initialCapacity];
- mValues = new long[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedLongArray(initialCapacity);
+ mValues = new long[mKeys.length];
}
mSize = 0;
}
@@ -140,17 +142,8 @@ public class LongSparseLongArray implements Cloneable {
} else {
i = ~i;
- if (mSize >= mKeys.length) {
- growKeyAndValueArrays(mSize + 1);
- }
-
- if (mSize - i != 0) {
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -234,27 +227,9 @@ public class LongSparseLongArray implements Cloneable {
return;
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- growKeyAndValueArrays(pos + 1);
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
- }
-
- private void growKeyAndValueArrays(int minNeededSize) {
- int n = ArrayUtils.idealLongArraySize(minNeededSize);
-
- long[] nkeys = new long[n];
- long[] nvalues = new long[n];
-
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 46d9d45..92e874f 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseArrays map integers to Objects. Unlike a normal array of Objects,
@@ -70,12 +73,11 @@ public class SparseArray<E> implements Cloneable {
*/
public SparseArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_INTS;
- mValues = ContainerHelpers.EMPTY_OBJECTS;
+ mKeys = EmptyArray.INT;
+ mValues = EmptyArray.OBJECT;
} else {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new Object[initialCapacity];
+ mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);
+ mKeys = new int[mValues.length];
}
mSize = 0;
}
@@ -215,28 +217,8 @@ public class SparseArray<E> implements Cloneable {
i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
}
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -368,24 +350,9 @@ public class SparseArray<E> implements Cloneable {
gc();
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index f59ef0f6d..e293b1f 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseBooleanArrays map integers to booleans.
@@ -57,12 +60,11 @@ public class SparseBooleanArray implements Cloneable {
*/
public SparseBooleanArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_INTS;
- mValues = ContainerHelpers.EMPTY_BOOLEANS;
+ mKeys = EmptyArray.INT;
+ mValues = EmptyArray.BOOLEAN;
} else {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new boolean[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedIntArray(initialCapacity);
+ mValues = new boolean[mKeys.length];
}
mSize = 0;
}
@@ -135,28 +137,8 @@ public class SparseBooleanArray implements Cloneable {
} else {
i = ~i;
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- boolean[] nvalues = new boolean[n];
-
- // Log.e("SparseBooleanArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseBooleanArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -245,24 +227,9 @@ public class SparseBooleanArray implements Cloneable {
return;
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- boolean[] nvalues = new boolean[n];
-
- // Log.e("SparseBooleanArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 4f5ca07..2b85a21 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseIntArrays map integers to integers. Unlike a normal array of integers,
@@ -60,12 +63,11 @@ public class SparseIntArray implements Cloneable {
*/
public SparseIntArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_INTS;
- mValues = ContainerHelpers.EMPTY_INTS;
+ mKeys = EmptyArray.INT;
+ mValues = EmptyArray.INT;
} else {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new int[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedIntArray(initialCapacity);
+ mValues = new int[mKeys.length];
}
mSize = 0;
}
@@ -138,28 +140,8 @@ public class SparseIntArray implements Cloneable {
} else {
i = ~i;
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- int[] nvalues = new int[n];
-
- // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseIntArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -243,24 +225,9 @@ public class SparseIntArray implements Cloneable {
return;
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- int[] nvalues = new int[n];
-
- // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index 39fc8a3..0166c4a 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseLongArrays map integers to longs. Unlike a normal array of longs,
@@ -60,12 +63,11 @@ public class SparseLongArray implements Cloneable {
*/
public SparseLongArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_INTS;
- mValues = ContainerHelpers.EMPTY_LONGS;
+ mKeys = EmptyArray.INT;
+ mValues = EmptyArray.LONG;
} else {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new long[initialCapacity];
+ mValues = ArrayUtils.newUnpaddedLongArray(initialCapacity);
+ mKeys = new int[mValues.length];
}
mSize = 0;
}
@@ -138,17 +140,8 @@ public class SparseLongArray implements Cloneable {
} else {
i = ~i;
- if (mSize >= mKeys.length) {
- growKeyAndValueArrays(mSize + 1);
- }
-
- if (mSize - i != 0) {
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -232,27 +225,9 @@ public class SparseLongArray implements Cloneable {
return;
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- growKeyAndValueArrays(pos + 1);
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
- }
-
- private void growKeyAndValueArrays(int minNeededSize) {
- int n = ArrayUtils.idealLongArraySize(minNeededSize);
-
- int[] nkeys = new int[n];
- long[] nvalues = new long[n];
-
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index abae068..477c994 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -52,7 +52,7 @@ import java.util.Queue;
*/
final class AccessibilityInteractionController {
- private static final boolean ENFORCE_NODE_TREE_CONSISTENT = Build.IS_DEBUGGABLE;
+ private static final boolean ENFORCE_NODE_TREE_CONSISTENT = false;
private final ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
new ArrayList<AccessibilityNodeInfo>();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f2b9b96..22ca418 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,6 +16,8 @@
package android.view;
+import android.animation.RevealAnimator;
+import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -10810,6 +10812,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Returns a ValueAnimator which can be used to run a reveal animation,
+ * clipping the content of the view to a circle.
+ *
+ * TODO: Make this a public API.
+ * @hide
+ */
+ public final ValueAnimator createRevealAnimator(int x, int y,
+ float startRadius, float endRadius, boolean inverseClip) {
+ return RevealAnimator.ofRevealCircle(this, x, y, startRadius, endRadius, inverseClip);
+ }
+
+ /**
* Sets the outline of the view, which defines the shape of the shadow it
* casts, and can used for clipping.
* <p>
@@ -10891,6 +10905,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
float x, float y, float radius) {
if (mDisplayList != null) {
mDisplayList.setRevealClip(shouldClip, inverseClip, x, y, radius);
+ // TODO: Handle this invalidate in a better way, or purely in native.
+ invalidate();
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e0e523e..fd85df9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -678,13 +678,13 @@ public final class ViewRootImpl implements ViewParent,
mAttachInfo.mHardwareAccelerationRequested = false;
// Don't enable hardware acceleration when the application is in compatibility mode
- if (mTranslator != null) return;
+ if (false && mTranslator != null) return;
// Try to enable hardware acceleration if requested
final boolean hardwareAccelerated =
(attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
- if (hardwareAccelerated) {
+ if (true || hardwareAccelerated) {
if (!HardwareRenderer.isAvailable()) {
return;
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 333e631..14e7951 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -25,6 +25,7 @@ import android.text.InputFilter;
import android.text.SpannableString;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import com.android.internal.widget.EditableInputConnection;
import android.R;
@@ -1341,7 +1342,7 @@ public class Editor {
if (layout instanceof DynamicLayout) {
if (mTextDisplayLists == null) {
- mTextDisplayLists = new TextDisplayList[ArrayUtils.idealObjectArraySize(0)];
+ mTextDisplayLists = ArrayUtils.emptyArray(TextDisplayList.class);
}
DynamicLayout dynamicLayout = (DynamicLayout) layout;
@@ -1441,10 +1442,7 @@ public class Editor {
}
// No available index found, the pool has to grow
- int newSize = ArrayUtils.idealIntArraySize(length + 1);
- TextDisplayList[] displayLists = new TextDisplayList[newSize];
- System.arraycopy(mTextDisplayLists, 0, displayLists, 0, length);
- mTextDisplayLists = displayLists;
+ mTextDisplayLists = GrowingArrayUtils.append(mTextDisplayLists, length, null);
return length;
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0d3df51..f7d20b53 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1516,6 +1516,75 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * Helper action to set a color filter on a compound drawable on a TextView. Supports relative
+ * (s/t/e/b) or cardinal (l/t/r/b) arrangement.
+ */
+ private class TextViewDrawableColorFilterAction extends Action {
+ public TextViewDrawableColorFilterAction(int viewId, boolean isRelative, int index,
+ int color, PorterDuff.Mode mode) {
+ this.viewId = viewId;
+ this.isRelative = isRelative;
+ this.index = index;
+ this.color = color;
+ this.mode = mode;
+ }
+
+ public TextViewDrawableColorFilterAction(Parcel parcel) {
+ viewId = parcel.readInt();
+ isRelative = (parcel.readInt() != 0);
+ index = parcel.readInt();
+ color = parcel.readInt();
+ mode = readPorterDuffMode(parcel);
+ }
+
+ private PorterDuff.Mode readPorterDuffMode(Parcel parcel) {
+ int mode = parcel.readInt();
+ if (mode >= 0 && mode < PorterDuff.Mode.values().length) {
+ return PorterDuff.Mode.values()[mode];
+ } else {
+ return PorterDuff.Mode.CLEAR;
+ }
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(TAG);
+ dest.writeInt(viewId);
+ dest.writeInt(isRelative ? 1 : 0);
+ dest.writeInt(index);
+ dest.writeInt(color);
+ dest.writeInt(mode.ordinal());
+ }
+
+ @Override
+ public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+ final TextView target = (TextView) root.findViewById(viewId);
+ if (target == null) return;
+ Drawable[] drawables = isRelative
+ ? target.getCompoundDrawablesRelative()
+ : target.getCompoundDrawables();
+ if (index < 0 || index >= 4) {
+ throw new IllegalStateException("index must be in range [0, 3].");
+ }
+ Drawable d = drawables[index];
+ if (d != null) {
+ d.mutate();
+ d.setColorFilter(color, mode);
+ }
+ }
+
+ public String getActionName() {
+ return "TextViewDrawableColorFilterAction";
+ }
+
+ final boolean isRelative;
+ final int index;
+ final int color;
+ final PorterDuff.Mode mode;
+
+ public final static int TAG = 17;
+ }
+
+ /**
* Simple class used to keep track of memory usage in a RemoteViews.
*
*/
@@ -1686,6 +1755,9 @@ public class RemoteViews implements Parcelable, Filter {
case SetRemoteViewsAdapterList.TAG:
mActions.add(new SetRemoteViewsAdapterList(parcel));
break;
+ case TextViewDrawableColorFilterAction.TAG:
+ mActions.add(new TextViewDrawableColorFilterAction(parcel));
+ break;
default:
throw new ActionException("Tag " + tag + " not found");
}
@@ -1921,6 +1993,28 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * Equivalent to applying a color filter on one of the drawables in
+ * {@link android.widget.TextView#getCompoundDrawablesRelative()}.
+ *
+ * @param viewId The id of the view whose text should change.
+ * @param index The index of the drawable in the array of
+ * {@link android.widget.TextView#getCompoundDrawablesRelative()} to set the color
+ * filter on. Must be in [0, 3].
+ * @param color The color of the color filter. See
+ * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}.
+ * @param mode The mode of the color filter. See
+ * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}.
+ * @hide
+ */
+ public void setTextViewCompoundDrawablesRelativeColorFilter(int viewId,
+ int index, int color, PorterDuff.Mode mode) {
+ if (index < 0 || index >= 4) {
+ throw new IllegalArgumentException("index must be in range [0, 3].");
+ }
+ addAction(new TextViewDrawableColorFilterAction(viewId, true, index, color, mode));
+ }
+
+ /**
* Equivalent to calling ImageView.setImageResource
*
* @param viewId The id of the view whose drawable should change
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 1eedc5d..d8a6867 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1171,8 +1171,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|| !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) {
if (mSearchable != null) {
launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString());
- setImeVisibility(false);
}
+ setImeVisibility(false);
dismissSuggestions();
}
}
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 1cda631..595f023 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -35,6 +35,7 @@ import android.view.textservice.TextInfo;
import android.view.textservice.TextServicesManager;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import java.text.BreakIterator;
import java.util.Locale;
@@ -105,9 +106,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
mTextView = textView;
// Arbitrary: these arrays will automatically double their sizes on demand
- final int size = ArrayUtils.idealObjectArraySize(1);
- mIds = new int[size];
- mSpellCheckSpans = new SpellCheckSpan[size];
+ final int size = 1;
+ mIds = ArrayUtils.newUnpaddedIntArray(size);
+ mSpellCheckSpans = new SpellCheckSpan[mIds.length];
setLocale(mTextView.getSpellCheckerLocale());
@@ -184,17 +185,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
if (mIds[i] < 0) return i;
}
- if (mLength == mSpellCheckSpans.length) {
- final int newSize = mLength * 2;
- int[] newIds = new int[newSize];
- SpellCheckSpan[] newSpellCheckSpans = new SpellCheckSpan[newSize];
- System.arraycopy(mIds, 0, newIds, 0, mLength);
- System.arraycopy(mSpellCheckSpans, 0, newSpellCheckSpans, 0, mLength);
- mIds = newIds;
- mSpellCheckSpans = newSpellCheckSpans;
- }
-
- mSpellCheckSpans[mLength] = new SpellCheckSpan();
+ mIds = GrowingArrayUtils.append(mIds, mLength, 0);
+ mSpellCheckSpans = GrowingArrayUtils.append(
+ mSpellCheckSpans, mLength, new SpellCheckSpan());
mLength++;
return mLength - 1;
}
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index b1535e3..882bec9 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -29,8 +29,11 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.webkit.WebViewFactory;
-import com.android.internal.util.ArrayUtils;
+
+import com.android.internal.util.GrowingArrayUtils;
+
import dalvik.system.VMRuntime;
+import libcore.util.EmptyArray;
import java.io.IOException;
import java.io.InputStream;
@@ -1621,21 +1624,10 @@ public final class ProcessStats implements Parcelable {
}
int addLongData(int index, int type, int num) {
- int tableLen = mAddLongTable != null ? mAddLongTable.length : 0;
- if (mAddLongTableSize >= tableLen) {
- int newSize = ArrayUtils.idealIntArraySize(tableLen + 1);
- int[] newTable = new int[newSize];
- if (tableLen > 0) {
- System.arraycopy(mAddLongTable, 0, newTable, 0, tableLen);
- }
- mAddLongTable = newTable;
- }
- if (mAddLongTableSize > 0 && mAddLongTableSize - index != 0) {
- System.arraycopy(mAddLongTable, index, mAddLongTable, index + 1,
- mAddLongTableSize - index);
- }
int off = allocLongData(num);
- mAddLongTable[index] = type | off;
+ mAddLongTable = GrowingArrayUtils.insert(
+ mAddLongTable != null ? mAddLongTable : EmptyArray.INT,
+ mAddLongTableSize, index, type | off);
mAddLongTableSize++;
return off;
}
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 9137d3c..d177410 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -16,11 +16,10 @@
package com.android.internal.util;
-import java.lang.reflect.Array;
+import dalvik.system.VMRuntime;
+import libcore.util.EmptyArray;
-// XXX these should be changed to reflect the actual memory allocator we use.
-// it looks like right now objects want to be powers of 2 minus 8
-// and the array size eats another 4 bytes
+import java.lang.reflect.Array;
/**
* ArrayUtils contains some methods that you can call to find out
@@ -28,46 +27,42 @@ import java.lang.reflect.Array;
*/
public class ArrayUtils
{
- private static Object[] EMPTY = new Object[0];
private static final int CACHE_SIZE = 73;
private static Object[] sCache = new Object[CACHE_SIZE];
private ArrayUtils() { /* cannot be instantiated */ }
- public static int idealByteArraySize(int need) {
- for (int i = 4; i < 32; i++)
- if (need <= (1 << i) - 12)
- return (1 << i) - 12;
-
- return need;
+ public static byte[] newUnpaddedByteArray(int minLen) {
+ return (byte[])VMRuntime.getRuntime().newUnpaddedArray(byte.class, minLen);
}
- public static int idealBooleanArraySize(int need) {
- return idealByteArraySize(need);
+ public static char[] newUnpaddedCharArray(int minLen) {
+ return (char[])VMRuntime.getRuntime().newUnpaddedArray(char.class, minLen);
}
- public static int idealShortArraySize(int need) {
- return idealByteArraySize(need * 2) / 2;
+ public static int[] newUnpaddedIntArray(int minLen) {
+ return (int[])VMRuntime.getRuntime().newUnpaddedArray(int.class, minLen);
}
- public static int idealCharArraySize(int need) {
- return idealByteArraySize(need * 2) / 2;
+ public static boolean[] newUnpaddedBooleanArray(int minLen) {
+ return (boolean[])VMRuntime.getRuntime().newUnpaddedArray(boolean.class, minLen);
}
- public static int idealIntArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
+ public static long[] newUnpaddedLongArray(int minLen) {
+ return (long[])VMRuntime.getRuntime().newUnpaddedArray(long.class, minLen);
}
- public static int idealFloatArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
+ public static float[] newUnpaddedFloatArray(int minLen) {
+ return (float[])VMRuntime.getRuntime().newUnpaddedArray(float.class, minLen);
}
- public static int idealObjectArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
+ public static Object[] newUnpaddedObjectArray(int minLen) {
+ return (Object[])VMRuntime.getRuntime().newUnpaddedArray(Object.class, minLen);
}
- public static int idealLongArraySize(int need) {
- return idealByteArraySize(need * 8) / 8;
+ @SuppressWarnings("unchecked")
+ public static <T> T[] newUnpaddedArray(Class<T> clazz, int minLen) {
+ return (T[])VMRuntime.getRuntime().newUnpaddedArray(clazz, minLen);
}
/**
@@ -102,9 +97,10 @@ public class ArrayUtils
* it will return the same empty array every time to avoid reallocation,
* although this is not guaranteed.
*/
+ @SuppressWarnings("unchecked")
public static <T> T[] emptyArray(Class<T> kind) {
if (kind == Object.class) {
- return (T[]) EMPTY;
+ return (T[]) EmptyArray.OBJECT;
}
int bucket = ((System.identityHashCode(kind) / 8) & 0x7FFFFFFF) % CACHE_SIZE;
diff --git a/core/java/com/android/internal/util/GrowingArrayUtils.java b/core/java/com/android/internal/util/GrowingArrayUtils.java
new file mode 100644
index 0000000..b4d2d730
--- /dev/null
+++ b/core/java/com/android/internal/util/GrowingArrayUtils.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+/**
+ * A helper class that aims to provide comparable growth performance to ArrayList, but on primitive
+ * arrays. Common array operations are implemented for efficient use in dynamic containers.
+ *
+ * All methods in this class assume that the length of an array is equivalent to its capacity and
+ * NOT the number of elements in the array. The current size of the array is always passed in as a
+ * parameter.
+ *
+ * @hide
+ */
+public final class GrowingArrayUtils {
+
+ /**
+ * Appends an element to the end of the array, growing the array if there is no more room.
+ * @param array The array to which to append the element. This must NOT be null.
+ * @param currentSize The number of elements in the array. Must be less than or equal to
+ * array.length.
+ * @param element The element to append.
+ * @return the array to which the element was appended. This may be different than the given
+ * array.
+ */
+ public static <T> T[] append(T[] array, int currentSize, T element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ @SuppressWarnings("unchecked")
+ T[] newArray = ArrayUtils.newUnpaddedArray(
+ (Class<T>) array.getClass().getComponentType(), growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive int version of {@link #append(Object[], int, Object)}.
+ */
+ public static int[] append(int[] array, int currentSize, int element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ int[] newArray = ArrayUtils.newUnpaddedIntArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive long version of {@link #append(Object[], int, Object)}.
+ */
+ public static long[] append(long[] array, int currentSize, long element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ long[] newArray = ArrayUtils.newUnpaddedLongArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive boolean version of {@link #append(Object[], int, Object)}.
+ */
+ public static boolean[] append(boolean[] array, int currentSize, boolean element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ boolean[] newArray = ArrayUtils.newUnpaddedBooleanArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Inserts an element into the array at the specified index, growing the array if there is no
+ * more room.
+ *
+ * @param array The array to which to append the element. Must NOT be null.
+ * @param currentSize The number of elements in the array. Must be less than or equal to
+ * array.length.
+ * @param element The element to insert.
+ * @return the array to which the element was appended. This may be different than the given
+ * array.
+ */
+ public static <T> T[] insert(T[] array, int currentSize, int index, T element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ @SuppressWarnings("unchecked")
+ T[] newArray = ArrayUtils.newUnpaddedArray((Class<T>)array.getClass().getComponentType(),
+ growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Primitive int version of {@link #insert(Object[], int, int, Object)}.
+ */
+ public static int[] insert(int[] array, int currentSize, int index, int element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ int[] newArray = ArrayUtils.newUnpaddedIntArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Primitive long version of {@link #insert(Object[], int, int, Object)}.
+ */
+ public static long[] insert(long[] array, int currentSize, int index, long element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ long[] newArray = ArrayUtils.newUnpaddedLongArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Primitive boolean version of {@link #insert(Object[], int, int, Object)}.
+ */
+ public static boolean[] insert(boolean[] array, int currentSize, int index, boolean element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ boolean[] newArray = ArrayUtils.newUnpaddedBooleanArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Given the current size of an array, returns an ideal size to which the array should grow.
+ * This is typically double the given size, but should not be relied upon to do so in the
+ * future.
+ */
+ public static int growSize(int currentSize) {
+ return currentSize <= 4 ? 8 : currentSize * 2;
+ }
+
+ // Uninstantiable
+ private GrowingArrayUtils() {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
index 540ba20..a5ce6e0 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -14,12 +14,14 @@
* limitations under the License
*/
-package com.android.systemui;
+package com.android.internal.util;
import android.graphics.Bitmap;
/**
* Utility class for image analysis and processing.
+ *
+ * @hide
*/
public class ImageUtils {
@@ -65,7 +67,7 @@ public class ImageUtils {
*
* Note that really transparent colors are always grayscale.
*/
- public boolean isGrayscale(int color) {
+ public static boolean isGrayscale(int color) {
int alpha = 0xFF & (color >> 24);
if (alpha < ALPHA_TOLERANCE) {
return true;
diff --git a/core/java/com/android/internal/util/LegacyNotificationUtil.java b/core/java/com/android/internal/util/LegacyNotificationUtil.java
new file mode 100644
index 0000000..0394bbc
--- /dev/null
+++ b/core/java/com/android/internal/util/LegacyNotificationUtil.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.util;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.style.TextAppearanceSpan;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.Arrays;
+import java.util.WeakHashMap;
+
+/**
+ * Helper class to process legacy (Holo) notifications to make them look like quantum notifications.
+ *
+ * @hide
+ */
+public class LegacyNotificationUtil {
+
+ private static final String TAG = "LegacyNotificationUtil";
+
+ private static final Object sLock = new Object();
+ private static LegacyNotificationUtil sInstance;
+
+ private final ImageUtils mImageUtils = new ImageUtils();
+ private final WeakHashMap<Bitmap, Pair<Boolean, Integer>> mGrayscaleBitmapCache =
+ new WeakHashMap<Bitmap, Pair<Boolean, Integer>>();
+
+ public static LegacyNotificationUtil getInstance() {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new LegacyNotificationUtil();
+ }
+ return sInstance;
+ }
+ }
+
+ /**
+ * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
+ * gray".
+ *
+ * @param bitmap The bitmap to test.
+ * @return Whether the bitmap is grayscale.
+ */
+ public boolean isGrayscale(Bitmap bitmap) {
+ synchronized (sLock) {
+ Pair<Boolean, Integer> cached = mGrayscaleBitmapCache.get(bitmap);
+ if (cached != null) {
+ if (cached.second == bitmap.getGenerationId()) {
+ return cached.first;
+ }
+ }
+ }
+ boolean result;
+ int generationId;
+ synchronized (mImageUtils) {
+ result = mImageUtils.isGrayscale(bitmap);
+
+ // generationId and the check whether the Bitmap is grayscale can't be read atomically
+ // here. However, since the thread is in the process of posting the notification, we can
+ // assume that it doesn't modify the bitmap while we are checking the pixels.
+ generationId = bitmap.getGenerationId();
+ }
+ synchronized (sLock) {
+ mGrayscaleBitmapCache.put(bitmap, Pair.create(result, generationId));
+ }
+ return result;
+ }
+
+ /**
+ * Checks whether a drawable is grayscale. Grayscale here means "very close to a perfect
+ * gray".
+ *
+ * @param d The drawable to test.
+ * @return Whether the drawable is grayscale.
+ */
+ public boolean isGrayscale(Drawable d) {
+ if (d == null) {
+ return false;
+ } else if (d instanceof BitmapDrawable) {
+ BitmapDrawable bd = (BitmapDrawable) d;
+ return bd.getBitmap() != null && isGrayscale(bd.getBitmap());
+ } else if (d instanceof AnimationDrawable) {
+ AnimationDrawable ad = (AnimationDrawable) d;
+ int count = ad.getNumberOfFrames();
+ return count > 0 && isGrayscale(ad.getFrame(0));
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Checks whether a drawable with a resoure id is grayscale. Grayscale here means "very close
+ * to a perfect gray".
+ *
+ * @param context The context to load the drawable from.
+ * @return Whether the drawable is grayscale.
+ */
+ public boolean isGrayscale(Context context, int drawableResId) {
+ if (drawableResId != 0) {
+ try {
+ return isGrayscale(context.getDrawable(drawableResId));
+ } catch (Resources.NotFoundException ex) {
+ Log.e(TAG, "Drawable not found: " + drawableResId);
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Inverts all the grayscale colors set by {@link android.text.style.TextAppearanceSpan}s on
+ * the text.
+ *
+ * @param charSequence The text to process.
+ * @return The color inverted text.
+ */
+ public CharSequence invertCharSequenceColors(CharSequence charSequence) {
+ if (charSequence instanceof Spanned) {
+ Spanned ss = (Spanned) charSequence;
+ Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+ SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+ for (Object span : spans) {
+ Object resultSpan = span;
+ if (span instanceof TextAppearanceSpan) {
+ resultSpan = processTextAppearanceSpan((TextAppearanceSpan) span);
+ }
+ builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
+ ss.getSpanFlags(span));
+ }
+ return builder;
+ }
+ return charSequence;
+ }
+
+ private TextAppearanceSpan processTextAppearanceSpan(TextAppearanceSpan span) {
+ ColorStateList colorStateList = span.getTextColor();
+ if (colorStateList != null) {
+ int[] colors = colorStateList.getColors();
+ boolean changed = false;
+ for (int i = 0; i < colors.length; i++) {
+ if (ImageUtils.isGrayscale(colors[i])) {
+
+ // Allocate a new array so we don't change the colors in the old color state
+ // list.
+ if (!changed) {
+ colors = Arrays.copyOf(colors, colors.length);
+ }
+ colors[i] = processColor(colors[i]);
+ changed = true;
+ }
+ }
+ if (changed) {
+ return new TextAppearanceSpan(
+ span.getFamily(), span.getTextStyle(), span.getTextSize(),
+ new ColorStateList(colorStateList.getStates(), colors),
+ span.getLinkTextColor());
+ }
+ }
+ return span;
+ }
+
+ private int processColor(int color) {
+ return Color.argb(Color.alpha(color),
+ 255 - Color.red(color),
+ 255 - Color.green(color),
+ 255 - Color.blue(color));
+ }
+}
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
deleted file mode 100644
index 4648f39..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ /dev/null
@@ -1,1270 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget.multiwaveview;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-
-/**
- * A special widget containing a center and outer ring. Moving the center ring to the outer ring
- * causes an event that can be caught by implementing OnTriggerListener.
- */
-public class MultiWaveView extends View {
- private static final String TAG = "MultiWaveView";
- private static final boolean DEBUG = false;
-
- // Wave state machine
- private static final int STATE_IDLE = 0;
- private static final int STATE_START = 1;
- private static final int STATE_FIRST_TOUCH = 2;
- private static final int STATE_TRACKING = 3;
- private static final int STATE_SNAP = 4;
- private static final int STATE_FINISH = 5;
-
- // Animation properties.
- private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
-
- public interface OnTriggerListener {
- int NO_HANDLE = 0;
- int CENTER_HANDLE = 1;
- public void onGrabbed(View v, int handle);
- public void onReleased(View v, int handle);
- public void onTrigger(View v, int target);
- public void onGrabbedStateChange(View v, int handle);
- public void onFinishFinalAnimation();
- }
-
- // Tuneable parameters for animation
- private static final int CHEVRON_INCREMENTAL_DELAY = 160;
- private static final int CHEVRON_ANIMATION_DURATION = 850;
- private static final int RETURN_TO_HOME_DELAY = 1200;
- private static final int RETURN_TO_HOME_DURATION = 200;
- private static final int HIDE_ANIMATION_DELAY = 200;
- private static final int HIDE_ANIMATION_DURATION = 200;
- private static final int SHOW_ANIMATION_DURATION = 200;
- private static final int SHOW_ANIMATION_DELAY = 50;
- private static final int INITIAL_SHOW_HANDLE_DURATION = 200;
-
- private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
- private static final float TARGET_SCALE_EXPANDED = 1.0f;
- private static final float TARGET_SCALE_COLLAPSED = 0.8f;
- private static final float RING_SCALE_EXPANDED = 1.0f;
- private static final float RING_SCALE_COLLAPSED = 0.5f;
-
- private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;
-
- private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
- private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
- private AnimationBundle mChevronAnimations = new AnimationBundle();
- private AnimationBundle mTargetAnimations = new AnimationBundle();
- private AnimationBundle mHandleAnimations = new AnimationBundle();
- private ArrayList<String> mTargetDescriptions;
- private ArrayList<String> mDirectionDescriptions;
- private OnTriggerListener mOnTriggerListener;
- private TargetDrawable mHandleDrawable;
- private TargetDrawable mOuterRing;
- private Vibrator mVibrator;
-
- private int mFeedbackCount = 3;
- private int mVibrationDuration = 0;
- private int mGrabbedState;
- private int mActiveTarget = -1;
- private float mTapRadius;
- private float mWaveCenterX;
- private float mWaveCenterY;
- private int mMaxTargetHeight;
- private int mMaxTargetWidth;
-
- private float mOuterRadius = 0.0f;
- private float mSnapMargin = 0.0f;
- private boolean mDragging;
- private int mNewTargetResources;
-
- private class AnimationBundle extends ArrayList<Tweener> {
- private static final long serialVersionUID = 0xA84D78726F127468L;
- private boolean mSuspended;
-
- public void start() {
- if (mSuspended) return; // ignore attempts to start animations
- final int count = size();
- for (int i = 0; i < count; i++) {
- Tweener anim = get(i);
- anim.animator.start();
- }
- }
-
- public void cancel() {
- final int count = size();
- for (int i = 0; i < count; i++) {
- Tweener anim = get(i);
- anim.animator.cancel();
- }
- clear();
- }
-
- public void stop() {
- final int count = size();
- for (int i = 0; i < count; i++) {
- Tweener anim = get(i);
- anim.animator.end();
- }
- clear();
- }
-
- public void setSuspended(boolean suspend) {
- mSuspended = suspend;
- }
- };
-
- private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
- dispatchOnFinishFinalAnimation();
- }
- };
-
- private AnimatorListener mResetListenerWithPing = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- ping();
- switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
- dispatchOnFinishFinalAnimation();
- }
- };
-
- private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- invalidateGlobalRegion(mHandleDrawable);
- invalidate();
- }
- };
-
- private boolean mAnimatingTargets;
- private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- if (mNewTargetResources != 0) {
- internalSetTargetResources(mNewTargetResources);
- mNewTargetResources = 0;
- hideTargets(false, false);
- }
- mAnimatingTargets = false;
- }
- };
- private int mTargetResourceId;
- private int mTargetDescriptionsResourceId;
- private int mDirectionDescriptionsResourceId;
- private boolean mAlwaysTrackFinger;
- private int mHorizontalInset;
- private int mVerticalInset;
- private int mGravity = Gravity.TOP;
- private boolean mInitialLayout = true;
- private Tweener mBackgroundAnimator;
-
- public MultiWaveView(Context context) {
- this(context, null);
- }
-
- public MultiWaveView(Context context, AttributeSet attrs) {
- super(context, attrs);
- Resources res = context.getResources();
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiWaveView);
- mOuterRadius = a.getDimension(R.styleable.MultiWaveView_outerRadius, mOuterRadius);
- mSnapMargin = a.getDimension(R.styleable.MultiWaveView_snapMargin, mSnapMargin);
- mVibrationDuration = a.getInt(R.styleable.MultiWaveView_vibrationDuration,
- mVibrationDuration);
- mFeedbackCount = a.getInt(R.styleable.MultiWaveView_feedbackCount,
- mFeedbackCount);
- mHandleDrawable = new TargetDrawable(res,
- a.peekValue(R.styleable.MultiWaveView_handleDrawable).resourceId);
- mTapRadius = mHandleDrawable.getWidth()/2;
- mOuterRing = new TargetDrawable(res,
- a.peekValue(R.styleable.MultiWaveView_waveDrawable).resourceId);
- mAlwaysTrackFinger = a.getBoolean(R.styleable.MultiWaveView_alwaysTrackFinger, false);
-
- // Read array of chevron drawables
- TypedValue outValue = new TypedValue();
- if (a.getValue(R.styleable.MultiWaveView_chevronDrawables, outValue)) {
- ArrayList<TargetDrawable> chevrons = loadDrawableArray(outValue.resourceId);
- for (int i = 0; i < chevrons.size(); i++) {
- final TargetDrawable chevron = chevrons.get(i);
- for (int k = 0; k < mFeedbackCount; k++) {
- mChevronDrawables.add(chevron == null ? null : new TargetDrawable(chevron));
- }
- }
- }
-
- // Read array of target drawables
- if (a.getValue(R.styleable.MultiWaveView_targetDrawables, outValue)) {
- internalSetTargetResources(outValue.resourceId);
- }
- if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
- throw new IllegalStateException("Must specify at least one target drawable");
- }
-
- // Read array of target descriptions
- if (a.getValue(R.styleable.MultiWaveView_targetDescriptions, outValue)) {
- final int resourceId = outValue.resourceId;
- if (resourceId == 0) {
- throw new IllegalStateException("Must specify target descriptions");
- }
- setTargetDescriptionsResourceId(resourceId);
- }
-
- // Read array of direction descriptions
- if (a.getValue(R.styleable.MultiWaveView_directionDescriptions, outValue)) {
- final int resourceId = outValue.resourceId;
- if (resourceId == 0) {
- throw new IllegalStateException("Must specify direction descriptions");
- }
- setDirectionDescriptionsResourceId(resourceId);
- }
-
- a.recycle();
-
- // Use gravity attribute from LinearLayout
- a = context.obtainStyledAttributes(attrs, android.R.styleable.LinearLayout);
- mGravity = a.getInt(android.R.styleable.LinearLayout_gravity, Gravity.TOP);
- a.recycle();
-
- setVibrateEnabled(mVibrationDuration > 0);
- assignDefaultsIfNeeded();
- }
-
- private void dump() {
- Log.v(TAG, "Outer Radius = " + mOuterRadius);
- Log.v(TAG, "SnapMargin = " + mSnapMargin);
- Log.v(TAG, "FeedbackCount = " + mFeedbackCount);
- Log.v(TAG, "VibrationDuration = " + mVibrationDuration);
- Log.v(TAG, "TapRadius = " + mTapRadius);
- Log.v(TAG, "WaveCenterX = " + mWaveCenterX);
- Log.v(TAG, "WaveCenterY = " + mWaveCenterY);
- }
-
- public void suspendAnimations() {
- mChevronAnimations.setSuspended(true);
- mTargetAnimations.setSuspended(true);
- mHandleAnimations.setSuspended(true);
- }
-
- public void resumeAnimations() {
- mChevronAnimations.setSuspended(false);
- mTargetAnimations.setSuspended(false);
- mHandleAnimations.setSuspended(false);
- mChevronAnimations.start();
- mTargetAnimations.start();
- mHandleAnimations.start();
- }
-
- @Override
- protected int getSuggestedMinimumWidth() {
- // View should be large enough to contain the background + handle and
- // target drawable on either edge.
- return (int) (Math.max(mOuterRing.getWidth(), 2 * mOuterRadius) + mMaxTargetWidth);
- }
-
- @Override
- protected int getSuggestedMinimumHeight() {
- // View should be large enough to contain the unlock ring + target and
- // target drawable on either edge
- return (int) (Math.max(mOuterRing.getHeight(), 2 * mOuterRadius) + mMaxTargetHeight);
- }
-
- private int resolveMeasured(int measureSpec, int desired)
- {
- int result = 0;
- int specSize = MeasureSpec.getSize(measureSpec);
- switch (MeasureSpec.getMode(measureSpec)) {
- case MeasureSpec.UNSPECIFIED:
- result = desired;
- break;
- case MeasureSpec.AT_MOST:
- result = Math.min(specSize, desired);
- break;
- case MeasureSpec.EXACTLY:
- default:
- result = specSize;
- }
- return result;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int minimumWidth = getSuggestedMinimumWidth();
- final int minimumHeight = getSuggestedMinimumHeight();
- int computedWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
- int computedHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
- computeInsets((computedWidth - minimumWidth), (computedHeight - minimumHeight));
- setMeasuredDimension(computedWidth, computedHeight);
- }
-
- private void switchToState(int state, float x, float y) {
- switch (state) {
- case STATE_IDLE:
- deactivateTargets();
- hideTargets(true, false);
- startBackgroundAnimation(0, 0.0f);
- mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
- break;
-
- case STATE_START:
- deactivateHandle(0, 0, 1.0f, null);
- startBackgroundAnimation(0, 0.0f);
- break;
-
- case STATE_FIRST_TOUCH:
- deactivateTargets();
- showTargets(true);
- mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
- startBackgroundAnimation(INITIAL_SHOW_HANDLE_DURATION, 1.0f);
- setGrabbedState(OnTriggerListener.CENTER_HANDLE);
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- announceTargets();
- }
- break;
-
- case STATE_TRACKING:
- break;
-
- case STATE_SNAP:
- break;
-
- case STATE_FINISH:
- doFinish();
- break;
- }
- }
-
- private void activateHandle(int duration, int delay, float finalAlpha,
- AnimatorListener finishListener) {
- mHandleAnimations.cancel();
- mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
- "ease", Ease.Cubic.easeIn,
- "delay", delay,
- "alpha", finalAlpha,
- "onUpdate", mUpdateListener,
- "onComplete", finishListener));
- mHandleAnimations.start();
- }
-
- private void deactivateHandle(int duration, int delay, float finalAlpha,
- AnimatorListener finishListener) {
- mHandleAnimations.cancel();
- mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
- "ease", Ease.Quart.easeOut,
- "delay", delay,
- "alpha", finalAlpha,
- "x", 0,
- "y", 0,
- "onUpdate", mUpdateListener,
- "onComplete", finishListener));
- mHandleAnimations.start();
- }
-
- /**
- * Animation used to attract user's attention to the target button.
- * Assumes mChevronDrawables is an a list with an even number of chevrons filled with
- * mFeedbackCount items in the order: left, right, top, bottom.
- */
- private void startChevronAnimation() {
- final float chevronStartDistance = mHandleDrawable.getWidth() * 0.8f;
- final float chevronStopDistance = mOuterRadius * 0.9f / 2.0f;
- final float startScale = 0.5f;
- final float endScale = 2.0f;
- final int directionCount = mFeedbackCount > 0 ? mChevronDrawables.size()/mFeedbackCount : 0;
-
- mChevronAnimations.stop();
-
- // Add an animation for all chevron drawables. There are mFeedbackCount drawables
- // in each direction and directionCount directions.
- for (int direction = 0; direction < directionCount; direction++) {
- double angle = 2.0 * Math.PI * direction / directionCount;
- final float sx = (float) Math.cos(angle);
- final float sy = 0.0f - (float) Math.sin(angle);
- final float[] xrange = new float[]
- {sx * chevronStartDistance, sx * chevronStopDistance};
- final float[] yrange = new float[]
- {sy * chevronStartDistance, sy * chevronStopDistance};
- for (int count = 0; count < mFeedbackCount; count++) {
- int delay = count * CHEVRON_INCREMENTAL_DELAY;
- final TargetDrawable icon = mChevronDrawables.get(direction*mFeedbackCount + count);
- if (icon == null) {
- continue;
- }
- mChevronAnimations.add(Tweener.to(icon, CHEVRON_ANIMATION_DURATION,
- "ease", mChevronAnimationInterpolator,
- "delay", delay,
- "x", xrange,
- "y", yrange,
- "alpha", new float[] {1.0f, 0.0f},
- "scaleX", new float[] {startScale, endScale},
- "scaleY", new float[] {startScale, endScale},
- "onUpdate", mUpdateListener));
- }
- }
- mChevronAnimations.start();
- }
-
- private void deactivateTargets() {
- final int count = mTargetDrawables.size();
- for (int i = 0; i < count; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- target.setState(TargetDrawable.STATE_INACTIVE);
- }
- mActiveTarget = -1;
- }
-
- void invalidateGlobalRegion(TargetDrawable drawable) {
- int width = drawable.getWidth();
- int height = drawable.getHeight();
- RectF childBounds = new RectF(0, 0, width, height);
- childBounds.offset(drawable.getX() - width/2, drawable.getY() - height/2);
- View view = this;
- while (view.getParent() != null && view.getParent() instanceof View) {
- view = (View) view.getParent();
- view.getMatrix().mapRect(childBounds);
- view.invalidate((int) Math.floor(childBounds.left),
- (int) Math.floor(childBounds.top),
- (int) Math.ceil(childBounds.right),
- (int) Math.ceil(childBounds.bottom));
- }
- }
-
- /**
- * Dispatches a trigger event to listener. Ignored if a listener is not set.
- * @param whichTarget the target that was triggered.
- */
- private void dispatchTriggerEvent(int whichTarget) {
- vibrate();
- if (mOnTriggerListener != null) {
- mOnTriggerListener.onTrigger(this, whichTarget);
- }
- }
-
- private void dispatchOnFinishFinalAnimation() {
- if (mOnTriggerListener != null) {
- mOnTriggerListener.onFinishFinalAnimation();
- }
- }
-
- private void doFinish() {
- final int activeTarget = mActiveTarget;
- final boolean targetHit = activeTarget != -1;
-
- if (targetHit) {
- if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
-
- highlightSelected(activeTarget);
-
- // Inform listener of any active targets. Typically only one will be active.
- deactivateHandle(RETURN_TO_HOME_DURATION, RETURN_TO_HOME_DELAY, 0.0f, mResetListener);
- dispatchTriggerEvent(activeTarget);
- if (!mAlwaysTrackFinger) {
- // Force ring and targets to finish animation to final expanded state
- mTargetAnimations.stop();
- }
- } else {
- // Animate handle back to the center based on current state.
- deactivateHandle(HIDE_ANIMATION_DURATION, HIDE_ANIMATION_DELAY, 1.0f,
- mResetListenerWithPing);
- hideTargets(true, false);
- }
-
- setGrabbedState(OnTriggerListener.NO_HANDLE);
- }
-
- private void highlightSelected(int activeTarget) {
- // Highlight the given target and fade others
- mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
- hideUnselected(activeTarget);
- }
-
- private void hideUnselected(int active) {
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- if (i != active) {
- mTargetDrawables.get(i).setAlpha(0.0f);
- }
- }
- }
-
- private void hideTargets(boolean animate, boolean expanded) {
- mTargetAnimations.cancel();
- // Note: these animations should complete at the same time so that we can swap out
- // the target assets asynchronously from the setTargetResources() call.
- mAnimatingTargets = animate;
- final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
- final int delay = animate ? HIDE_ANIMATION_DELAY : 0;
-
- final float targetScale = expanded ? TARGET_SCALE_EXPANDED : TARGET_SCALE_COLLAPSED;
- final int length = mTargetDrawables.size();
- for (int i = 0; i < length; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- target.setState(TargetDrawable.STATE_INACTIVE);
- mTargetAnimations.add(Tweener.to(target, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 0.0f,
- "scaleX", targetScale,
- "scaleY", targetScale,
- "delay", delay,
- "onUpdate", mUpdateListener));
- }
-
- final float ringScaleTarget = expanded ? RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
- mTargetAnimations.add(Tweener.to(mOuterRing, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 0.0f,
- "scaleX", ringScaleTarget,
- "scaleY", ringScaleTarget,
- "delay", delay,
- "onUpdate", mUpdateListener,
- "onComplete", mTargetUpdateListener));
-
- mTargetAnimations.start();
- }
-
- private void showTargets(boolean animate) {
- mTargetAnimations.stop();
- mAnimatingTargets = animate;
- final int delay = animate ? SHOW_ANIMATION_DELAY : 0;
- final int duration = animate ? SHOW_ANIMATION_DURATION : 0;
- final int length = mTargetDrawables.size();
- for (int i = 0; i < length; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- target.setState(TargetDrawable.STATE_INACTIVE);
- mTargetAnimations.add(Tweener.to(target, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 1.0f,
- "scaleX", 1.0f,
- "scaleY", 1.0f,
- "delay", delay,
- "onUpdate", mUpdateListener));
- }
- mTargetAnimations.add(Tweener.to(mOuterRing, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 1.0f,
- "scaleX", 1.0f,
- "scaleY", 1.0f,
- "delay", delay,
- "onUpdate", mUpdateListener,
- "onComplete", mTargetUpdateListener));
-
- mTargetAnimations.start();
- }
-
- private void vibrate() {
- final boolean hapticEnabled = Settings.System.getIntForUser(
- mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
- UserHandle.USER_CURRENT) != 0;
- if (mVibrator != null && hapticEnabled) {
- mVibrator.vibrate(mVibrationDuration, AudioManager.STREAM_SYSTEM);
- }
- }
-
- private ArrayList<TargetDrawable> loadDrawableArray(int resourceId) {
- Resources res = getContext().getResources();
- TypedArray array = res.obtainTypedArray(resourceId);
- final int count = array.length();
- ArrayList<TargetDrawable> drawables = new ArrayList<TargetDrawable>(count);
- for (int i = 0; i < count; i++) {
- TypedValue value = array.peekValue(i);
- TargetDrawable target = new TargetDrawable(res, value != null ? value.resourceId : 0);
- drawables.add(target);
- }
- array.recycle();
- return drawables;
- }
-
- private void internalSetTargetResources(int resourceId) {
- mTargetDrawables = loadDrawableArray(resourceId);
- mTargetResourceId = resourceId;
- final int count = mTargetDrawables.size();
- int maxWidth = mHandleDrawable.getWidth();
- int maxHeight = mHandleDrawable.getHeight();
- for (int i = 0; i < count; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- maxWidth = Math.max(maxWidth, target.getWidth());
- maxHeight = Math.max(maxHeight, target.getHeight());
- }
- if (mMaxTargetWidth != maxWidth || mMaxTargetHeight != maxHeight) {
- mMaxTargetWidth = maxWidth;
- mMaxTargetHeight = maxHeight;
- requestLayout(); // required to resize layout and call updateTargetPositions()
- } else {
- updateTargetPositions(mWaveCenterX, mWaveCenterY);
- updateChevronPositions(mWaveCenterX, mWaveCenterY);
- }
- }
-
- /**
- * Loads an array of drawables from the given resourceId.
- *
- * @param resourceId
- */
- public void setTargetResources(int resourceId) {
- if (mAnimatingTargets) {
- // postpone this change until we return to the initial state
- mNewTargetResources = resourceId;
- } else {
- internalSetTargetResources(resourceId);
- }
- }
-
- public int getTargetResourceId() {
- return mTargetResourceId;
- }
-
- /**
- * Sets the resource id specifying the target descriptions for accessibility.
- *
- * @param resourceId The resource id.
- */
- public void setTargetDescriptionsResourceId(int resourceId) {
- mTargetDescriptionsResourceId = resourceId;
- if (mTargetDescriptions != null) {
- mTargetDescriptions.clear();
- }
- }
-
- /**
- * Gets the resource id specifying the target descriptions for accessibility.
- *
- * @return The resource id.
- */
- public int getTargetDescriptionsResourceId() {
- return mTargetDescriptionsResourceId;
- }
-
- /**
- * Sets the resource id specifying the target direction descriptions for accessibility.
- *
- * @param resourceId The resource id.
- */
- public void setDirectionDescriptionsResourceId(int resourceId) {
- mDirectionDescriptionsResourceId = resourceId;
- if (mDirectionDescriptions != null) {
- mDirectionDescriptions.clear();
- }
- }
-
- /**
- * Gets the resource id specifying the target direction descriptions.
- *
- * @return The resource id.
- */
- public int getDirectionDescriptionsResourceId() {
- return mDirectionDescriptionsResourceId;
- }
-
- /**
- * Enable or disable vibrate on touch.
- *
- * @param enabled
- */
- public void setVibrateEnabled(boolean enabled) {
- if (enabled && mVibrator == null) {
- mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
- } else {
- mVibrator = null;
- }
- }
-
- /**
- * Starts chevron animation. Example use case: show chevron animation whenever the phone rings
- * or the user touches the screen.
- *
- */
- public void ping() {
- startChevronAnimation();
- }
-
- /**
- * Resets the widget to default state and cancels all animation. If animate is 'true', will
- * animate objects into place. Otherwise, objects will snap back to place.
- *
- * @param animate
- */
- public void reset(boolean animate) {
- mChevronAnimations.stop();
- mHandleAnimations.stop();
- mTargetAnimations.stop();
- startBackgroundAnimation(0, 0.0f);
- hideChevrons();
- hideTargets(animate, false);
- deactivateHandle(0, 0, 1.0f, null);
- Tweener.reset();
- }
-
- private void startBackgroundAnimation(int duration, float alpha) {
- Drawable background = getBackground();
- if (mAlwaysTrackFinger && background != null) {
- if (mBackgroundAnimator != null) {
- mBackgroundAnimator.animator.end();
- }
- mBackgroundAnimator = Tweener.to(background, duration,
- "ease", Ease.Cubic.easeIn,
- "alpha", new int[] {0, (int)(255.0f * alpha)},
- "delay", SHOW_ANIMATION_DELAY);
- mBackgroundAnimator.animator.start();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- final int action = event.getAction();
- boolean handled = false;
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- if (DEBUG) Log.v(TAG, "*** DOWN ***");
- handleDown(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (DEBUG) Log.v(TAG, "*** MOVE ***");
- handleMove(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_UP:
- if (DEBUG) Log.v(TAG, "*** UP ***");
- handleMove(event);
- handleUp(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_CANCEL:
- if (DEBUG) Log.v(TAG, "*** CANCEL ***");
- handleMove(event);
- handleCancel(event);
- handled = true;
- break;
- }
- invalidate();
- return handled ? true : super.onTouchEvent(event);
- }
-
- private void moveHandleTo(float x, float y, boolean animate) {
- mHandleDrawable.setX(x);
- mHandleDrawable.setY(y);
- }
-
- private void handleDown(MotionEvent event) {
- float eventX = event.getX();
- float eventY = event.getY();
- switchToState(STATE_START, eventX, eventY);
- if (!trySwitchToFirstTouchState(eventX, eventY)) {
- mDragging = false;
- ping();
- }
- }
-
- private void handleUp(MotionEvent event) {
- if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
- switchToState(STATE_FINISH, event.getX(), event.getY());
- }
-
- private void handleCancel(MotionEvent event) {
- if (DEBUG && mDragging) Log.v(TAG, "** Handle CANCEL");
-
- // We should drop the active target here but it interferes with
- // moving off the screen in the direction of the navigation bar. At some point we may
- // want to revisit how we handle this. For now we'll allow a canceled event to
- // activate the current target.
-
- // mActiveTarget = -1; // Drop the active target if canceled.
-
- switchToState(STATE_FINISH, event.getX(), event.getY());
- }
-
- private void handleMove(MotionEvent event) {
- int activeTarget = -1;
- final int historySize = event.getHistorySize();
- ArrayList<TargetDrawable> targets = mTargetDrawables;
- int ntargets = targets.size();
- float x = 0.0f;
- float y = 0.0f;
- for (int k = 0; k < historySize + 1; k++) {
- float eventX = k < historySize ? event.getHistoricalX(k) : event.getX();
- float eventY = k < historySize ? event.getHistoricalY(k) : event.getY();
- // tx and ty are relative to wave center
- float tx = eventX - mWaveCenterX;
- float ty = eventY - mWaveCenterY;
- float touchRadius = (float) Math.sqrt(dist2(tx, ty));
- final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
- float limitX = tx * scale;
- float limitY = ty * scale;
- double angleRad = Math.atan2(-ty, tx);
-
- if (!mDragging) {
- trySwitchToFirstTouchState(eventX, eventY);
- }
-
- if (mDragging) {
- // For multiple targets, snap to the one that matches
- final float snapRadius = mOuterRadius - mSnapMargin;
- final float snapDistance2 = snapRadius * snapRadius;
- // Find first target in range
- for (int i = 0; i < ntargets; i++) {
- TargetDrawable target = targets.get(i);
-
- double targetMinRad = (i - 0.5) * 2 * Math.PI / ntargets;
- double targetMaxRad = (i + 0.5) * 2 * Math.PI / ntargets;
- if (target.isEnabled()) {
- boolean angleMatches =
- (angleRad > targetMinRad && angleRad <= targetMaxRad) ||
- (angleRad + 2 * Math.PI > targetMinRad &&
- angleRad + 2 * Math.PI <= targetMaxRad);
- if (angleMatches && (dist2(tx, ty) > snapDistance2)) {
- activeTarget = i;
- }
- }
- }
- }
- x = limitX;
- y = limitY;
- }
-
- if (!mDragging) {
- return;
- }
-
- if (activeTarget != -1) {
- switchToState(STATE_SNAP, x,y);
- moveHandleTo(x, y, false);
- } else {
- switchToState(STATE_TRACKING, x, y);
- moveHandleTo(x, y, false);
- }
-
- // Draw handle outside parent's bounds
- invalidateGlobalRegion(mHandleDrawable);
-
- if (mActiveTarget != activeTarget) {
- // Defocus the old target
- if (mActiveTarget != -1) {
- TargetDrawable target = targets.get(mActiveTarget);
- if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
- target.setState(TargetDrawable.STATE_INACTIVE);
- }
- }
- // Focus the new target
- if (activeTarget != -1) {
- TargetDrawable target = targets.get(activeTarget);
- if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
- target.setState(TargetDrawable.STATE_FOCUSED);
- }
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- String targetContentDescription = getTargetDescription(activeTarget);
- announceText(targetContentDescription);
- }
- activateHandle(0, 0, 0.0f, null);
- } else {
- activateHandle(0, 0, 1.0f, null);
- }
- }
- mActiveTarget = activeTarget;
- }
-
- @Override
- public boolean onHoverEvent(MotionEvent event) {
- if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
- final int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_HOVER_ENTER:
- event.setAction(MotionEvent.ACTION_DOWN);
- break;
- case MotionEvent.ACTION_HOVER_MOVE:
- event.setAction(MotionEvent.ACTION_MOVE);
- break;
- case MotionEvent.ACTION_HOVER_EXIT:
- event.setAction(MotionEvent.ACTION_UP);
- break;
- }
- onTouchEvent(event);
- event.setAction(action);
- }
- return super.onHoverEvent(event);
- }
-
- /**
- * Sets the current grabbed state, and dispatches a grabbed state change
- * event to our listener.
- */
- private void setGrabbedState(int newState) {
- if (newState != mGrabbedState) {
- if (newState != OnTriggerListener.NO_HANDLE) {
- vibrate();
- }
- mGrabbedState = newState;
- if (mOnTriggerListener != null) {
- if (newState == OnTriggerListener.NO_HANDLE) {
- mOnTriggerListener.onReleased(this, OnTriggerListener.CENTER_HANDLE);
- } else {
- mOnTriggerListener.onGrabbed(this, OnTriggerListener.CENTER_HANDLE);
- }
- mOnTriggerListener.onGrabbedStateChange(this, newState);
- }
- }
- }
-
- private boolean trySwitchToFirstTouchState(float x, float y) {
- final float tx = x - mWaveCenterX;
- final float ty = y - mWaveCenterY;
- if (mAlwaysTrackFinger || dist2(tx,ty) <= getScaledTapRadiusSquared()) {
- if (DEBUG) Log.v(TAG, "** Handle HIT");
- switchToState(STATE_FIRST_TOUCH, x, y);
- moveHandleTo(tx, ty, false);
- mDragging = true;
- return true;
- }
- return false;
- }
-
- private void assignDefaultsIfNeeded() {
- if (mOuterRadius == 0.0f) {
- mOuterRadius = Math.max(mOuterRing.getWidth(), mOuterRing.getHeight())/2.0f;
- }
- if (mSnapMargin == 0.0f) {
- mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
- }
- }
-
- private void computeInsets(int dx, int dy) {
- final int layoutDirection = getLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
- switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- mHorizontalInset = 0;
- break;
- case Gravity.RIGHT:
- mHorizontalInset = dx;
- break;
- case Gravity.CENTER_HORIZONTAL:
- default:
- mHorizontalInset = dx / 2;
- break;
- }
- switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
- case Gravity.TOP:
- mVerticalInset = 0;
- break;
- case Gravity.BOTTOM:
- mVerticalInset = dy;
- break;
- case Gravity.CENTER_VERTICAL:
- default:
- mVerticalInset = dy / 2;
- break;
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- final int width = right - left;
- final int height = bottom - top;
-
- // Target placement width/height. This puts the targets on the greater of the ring
- // width or the specified outer radius.
- final float placementWidth = Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
- final float placementHeight = Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
- float newWaveCenterX = mHorizontalInset
- + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
- float newWaveCenterY = mVerticalInset
- + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
-
- if (mInitialLayout) {
- hideChevrons();
- hideTargets(false, false);
- moveHandleTo(0, 0, false);
- mInitialLayout = false;
- }
-
- mOuterRing.setPositionX(newWaveCenterX);
- mOuterRing.setPositionY(newWaveCenterY);
-
- mHandleDrawable.setPositionX(newWaveCenterX);
- mHandleDrawable.setPositionY(newWaveCenterY);
-
- updateTargetPositions(newWaveCenterX, newWaveCenterY);
- updateChevronPositions(newWaveCenterX, newWaveCenterY);
-
- mWaveCenterX = newWaveCenterX;
- mWaveCenterY = newWaveCenterY;
-
- if (DEBUG) dump();
- }
-
- private void updateTargetPositions(float centerX, float centerY) {
- // Reposition the target drawables if the view changed.
- ArrayList<TargetDrawable> targets = mTargetDrawables;
- final int size = targets.size();
- final float alpha = (float) (-2.0f * Math.PI / size);
- for (int i = 0; i < size; i++) {
- final TargetDrawable targetIcon = targets.get(i);
- final float angle = alpha * i;
- targetIcon.setPositionX(centerX);
- targetIcon.setPositionY(centerY);
- targetIcon.setX(mOuterRadius * (float) Math.cos(angle));
- targetIcon.setY(mOuterRadius * (float) Math.sin(angle));
- }
- }
-
- private void updateChevronPositions(float centerX, float centerY) {
- ArrayList<TargetDrawable> chevrons = mChevronDrawables;
- final int size = chevrons.size();
- for (int i = 0; i < size; i++) {
- TargetDrawable target = chevrons.get(i);
- if (target != null) {
- target.setPositionX(centerX);
- target.setPositionY(centerY);
- }
- }
- }
-
- private void hideChevrons() {
- ArrayList<TargetDrawable> chevrons = mChevronDrawables;
- final int size = chevrons.size();
- for (int i = 0; i < size; i++) {
- TargetDrawable chevron = chevrons.get(i);
- if (chevron != null) {
- chevron.setAlpha(0.0f);
- }
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- mOuterRing.draw(canvas);
- final int ntargets = mTargetDrawables.size();
- for (int i = 0; i < ntargets; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- if (target != null) {
- target.draw(canvas);
- }
- }
- final int nchevrons = mChevronDrawables.size();
- for (int i = 0; i < nchevrons; i++) {
- TargetDrawable chevron = mChevronDrawables.get(i);
- if (chevron != null) {
- chevron.draw(canvas);
- }
- }
- mHandleDrawable.draw(canvas);
- }
-
- public void setOnTriggerListener(OnTriggerListener listener) {
- mOnTriggerListener = listener;
- }
-
- private float square(float d) {
- return d * d;
- }
-
- private float dist2(float dx, float dy) {
- return dx*dx + dy*dy;
- }
-
- private float getScaledTapRadiusSquared() {
- final float scaledTapRadius;
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- scaledTapRadius = TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mTapRadius;
- } else {
- scaledTapRadius = mTapRadius;
- }
- return square(scaledTapRadius);
- }
-
- private void announceTargets() {
- StringBuilder utterance = new StringBuilder();
- final int targetCount = mTargetDrawables.size();
- for (int i = 0; i < targetCount; i++) {
- String targetDescription = getTargetDescription(i);
- String directionDescription = getDirectionDescription(i);
- if (!TextUtils.isEmpty(targetDescription)
- && !TextUtils.isEmpty(directionDescription)) {
- String text = String.format(directionDescription, targetDescription);
- utterance.append(text);
- }
- if (utterance.length() > 0) {
- announceText(utterance.toString());
- }
- }
- }
-
- private void announceText(String text) {
- setContentDescription(text);
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
- setContentDescription(null);
- }
-
- private String getTargetDescription(int index) {
- if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
- mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
- if (mTargetDrawables.size() != mTargetDescriptions.size()) {
- Log.w(TAG, "The number of target drawables must be"
- + " euqal to the number of target descriptions.");
- return null;
- }
- }
- return mTargetDescriptions.get(index);
- }
-
- private String getDirectionDescription(int index) {
- if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
- mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
- if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
- Log.w(TAG, "The number of target drawables must be"
- + " euqal to the number of direction descriptions.");
- return null;
- }
- }
- return mDirectionDescriptions.get(index);
- }
-
- private ArrayList<String> loadDescriptions(int resourceId) {
- TypedArray array = getContext().getResources().obtainTypedArray(resourceId);
- final int count = array.length();
- ArrayList<String> targetContentDescriptions = new ArrayList<String>(count);
- for (int i = 0; i < count; i++) {
- String contentDescription = array.getString(i);
- targetContentDescriptions.add(contentDescription);
- }
- array.recycle();
- return targetContentDescriptions;
- }
-
- public int getResourceIdForTarget(int index) {
- final TargetDrawable drawable = mTargetDrawables.get(index);
- return drawable == null ? 0 : drawable.getResourceId();
- }
-
- public void setEnableTarget(int resourceId, boolean enabled) {
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- final TargetDrawable target = mTargetDrawables.get(i);
- if (target.getResourceId() == resourceId) {
- target.setEnabled(enabled);
- break; // should never be more than one match
- }
- }
- }
-
- /**
- * Gets the position of a target in the array that matches the given resource.
- * @param resourceId
- * @return the index or -1 if not found
- */
- public int getTargetPosition(int resourceId) {
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- final TargetDrawable target = mTargetDrawables.get(i);
- if (target.getResourceId() == resourceId) {
- return i; // should never be more than one match
- }
- }
- return -1;
- }
-
- private boolean replaceTargetDrawables(Resources res, int existingResourceId,
- int newResourceId) {
- if (existingResourceId == 0 || newResourceId == 0) {
- return false;
- }
-
- boolean result = false;
- final ArrayList<TargetDrawable> drawables = mTargetDrawables;
- final int size = drawables.size();
- for (int i = 0; i < size; i++) {
- final TargetDrawable target = drawables.get(i);
- if (target != null && target.getResourceId() == existingResourceId) {
- target.setDrawable(res, newResourceId);
- result = true;
- }
- }
-
- if (result) {
- requestLayout(); // in case any given drawable's size changes
- }
-
- return result;
- }
-
- /**
- * Searches the given package for a resource to use to replace the Drawable on the
- * target with the given resource id
- * @param component of the .apk that contains the resource
- * @param name of the metadata in the .apk
- * @param existingResId the resource id of the target to search for
- * @return true if found in the given package and replaced at least one target Drawables
- */
- public boolean replaceTargetDrawablesIfPresent(ComponentName component, String name,
- int existingResId) {
- if (existingResId == 0) return false;
-
- try {
- PackageManager packageManager = mContext.getPackageManager();
- // Look for the search icon specified in the activity meta-data
- Bundle metaData = packageManager.getActivityInfo(
- component, PackageManager.GET_META_DATA).metaData;
- if (metaData != null) {
- int iconResId = metaData.getInt(name);
- if (iconResId != 0) {
- Resources res = packageManager.getResourcesForActivity(component);
- return replaceTargetDrawables(res, existingResId, iconResId);
- }
- }
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Failed to swap drawable; "
- + component.flattenToShortString() + " not found", e);
- } catch (Resources.NotFoundException nfe) {
- Log.w(TAG, "Failed to swap drawable from "
- + component.flattenToShortString(), nfe);
- }
- return false;
- }
-}
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 2b9a5c4..b89dced 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -7,6 +7,7 @@
#include "SkImageDecoder.h"
#include "SkImageRef_ashmem.h"
#include "SkImageRef_GlobalPool.h"
+#include "SkMath.h"
#include "SkPixelRef.h"
#include "SkStream.h"
#include "SkTemplates.h"
@@ -146,15 +147,15 @@ static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStreamRewindable* stream,
return pr;
}
-static SkBitmap::Config configForScaledOutput(SkBitmap::Config config) {
- switch (config) {
- case SkBitmap::kNo_Config:
- case SkBitmap::kIndex8_Config:
- return SkBitmap::kARGB_8888_Config;
+static SkColorType colorTypeForScaledOutput(SkColorType colorType) {
+ switch (colorType) {
+ case kUnknown_SkColorType:
+ case kIndex_8_SkColorType:
+ return kPMColor_SkColorType;
default:
break;
}
- return config;
+ return colorType;
}
class ScaleCheckingAllocator : public SkBitmap::HeapAllocator {
@@ -165,8 +166,8 @@ public:
virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
// accounts for scale in final allocation, using eventual size and config
- const int bytesPerPixel = SkBitmap::ComputeBytesPerPixel(
- configForScaledOutput(bitmap->config()));
+ const int bytesPerPixel = SkColorTypeBytesPerPixel(
+ colorTypeForScaledOutput(bitmap->colorType()));
const int requestedSize = bytesPerPixel *
int(bitmap->width() * mScale + 0.5f) *
int(bitmap->height() * mScale + 0.5f);
@@ -194,21 +195,28 @@ public:
}
virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
- if (!bitmap->getSize64().is32() || bitmap->getSize() > mSize) {
- ALOGW("bitmap marked for reuse (%d bytes) can't fit new bitmap (%d bytes)",
- mSize, bitmap->getSize());
+ const SkImageInfo& info = bitmap->info();
+ if (info.fColorType == kUnknown_SkColorType) {
+ ALOGW("unable to reuse a bitmap as the target has an unknown bitmap configuration");
return false;
}
- SkImageInfo bitmapInfo;
- if (!bitmap->asImageInfo(&bitmapInfo)) {
- ALOGW("unable to reuse a bitmap as the target has an unknown bitmap configuration");
+ const int64_t size64 = info.getSafeSize64(bitmap->rowBytes());
+ if (!sk_64_isS32(size64)) {
+ ALOGW("bitmap is too large");
+ return false;
+ }
+
+ const size_t size = sk_64_asS32(size64);
+ if (size > mSize) {
+ ALOGW("bitmap marked for reuse (%d bytes) can't fit new bitmap (%d bytes)",
+ mSize, size);
return false;
}
// Create a new pixelref with the new ctable that wraps the previous pixelref
SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef),
- bitmapInfo, bitmap->rowBytes(), ctable);
+ info, bitmap->rowBytes(), ctable);
bitmap->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
@@ -416,12 +424,12 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
const float sy = scaledHeight / float(decodingBitmap.height());
// TODO: avoid copying when scaled size equals decodingBitmap size
- SkBitmap::Config config = configForScaledOutput(decodingBitmap.config());
+ SkColorType colorType = colorTypeForScaledOutput(decodingBitmap.colorType());
// FIXME: If the alphaType is kUnpremul and the image has alpha, the
// colors may not be correct, since Skia does not yet support drawing
// to/from unpremultiplied bitmaps.
- outputBitmap->setConfig(config, scaledWidth, scaledHeight, 0,
- decodingBitmap.alphaType());
+ outputBitmap->setConfig(SkImageInfo::Make(scaledWidth, scaledHeight,
+ colorType, decodingBitmap.alphaType()));
if (!outputBitmap->allocPixels(outputAllocator, NULL)) {
return nullObjectReturn("allocation failed for scaled bitmap");
}
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 7420055..946b898 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -680,9 +680,6 @@ public:
indices [ptCount * sizeof(uint16_t)]
*/
ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
-#ifdef SK_SCALAR_IS_FIXED
- storageSize += ptCount * sizeof(SkPoint); // storage for verts
-#endif
storageSize += indexCount * sizeof(uint16_t); // indices[]
SkAutoMalloc storage(storageSize);
@@ -693,16 +690,7 @@ public:
verts = (SkPoint*)(vertA.ptr() + vertIndex);
indices = (uint16_t*)(texs + ptCount);
#else
- verts = texs + ptCount;
- indices = (uint16_t*)(verts + ptCount);
- // convert floats to fixed
- {
- const float* src = vertA.ptr() + vertIndex;
- for (int i = 0; i < ptCount; i++) {
- verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
- src += 2;
- }
- }
+ SkASSERT(false);
#endif
// cons up texture coordinates and indices
@@ -804,25 +792,7 @@ public:
texs = (SkPoint*)(texA.ptr() + texIndex);
}
#else
- int count = ptCount; // for verts
- if (jtexs != NULL) {
- count += ptCount; // += for texs
- }
- SkAutoMalloc storage(count * sizeof(SkPoint));
- verts = (SkPoint*)storage.get();
- const float* src = vertA.ptr() + vertIndex;
- for (int i = 0; i < ptCount; i++) {
- verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
- src += 2;
- }
- if (jtexs != NULL) {
- texs = verts + ptCount;
- src = texA.ptr() + texIndex;
- for (int i = 0; i < ptCount; i++) {
- texs[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
- src += 2;
- }
- }
+ SkASSERT(false);
#endif
const SkColor* colors = NULL;
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 09589bd..a59ed19 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -50,14 +50,10 @@ public:
AutoJavaFloatArray autoArray(env, jarray, 20);
const float* src = autoArray.ptr();
-#ifdef SK_SCALAR_IS_FIXED
- SkFixed array[20];
- for (int i = 0; i < 20; i++) {
- array[i] = SkFloatToScalar(src[i]);
- }
- return reinterpret_cast<jlong>(new SkColorMatrixFilter(array));
-#else
+#ifdef SK_SCALAR_IS_FLOAT
return reinterpret_cast<jlong>(new SkColorMatrixFilter(src));
+#else
+ SkASSERT(false);
#endif
}
};
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 98edbdb..2883be9 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -6,6 +6,7 @@
#include "SkCanvas.h"
#include "SkDevice.h"
+#include "SkMath.h"
#include "SkPicture.h"
#include "SkRegion.h"
#include <android_runtime/AndroidRuntime.h>
@@ -564,21 +565,20 @@ void AndroidPixelRef::globalUnref() {
jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
SkColorTable* ctable) {
- Sk64 size64 = bitmap->getSize64();
- if (size64.isNeg() || !size64.is32()) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "bitmap size exceeds 32bits");
+ const SkImageInfo& info = bitmap->info();
+ if (info.fColorType == kUnknown_SkColorType) {
+ doThrowIAE(env, "unknown bitmap configuration");
return NULL;
}
- SkImageInfo bitmapInfo;
- if (!bitmap->asImageInfo(&bitmapInfo)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "unknown bitmap configuration");
+ const int64_t size64 = info.getSafeSize64(bitmap->rowBytes());
+ if (!sk_64_isS32(size64)) {
+ doThrowIAE(env, "bitmap size exceeds 32bits");
return NULL;
}
+ const size_t size = sk_64_asS32(size64);
+ SkASSERT(size == info.getSafeSize(bitmap->rowBytes()));
- size_t size = size64.get32();
jbyteArray arrayObj = (jbyteArray) env->CallObjectMethod(gVMRuntime,
gVMRuntime_newNonMovableArray,
gByte_class, size);
@@ -591,7 +591,7 @@ jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
return NULL;
}
SkASSERT(addr);
- SkPixelRef* pr = new AndroidPixelRef(env, bitmapInfo, (void*) addr,
+ SkPixelRef* pr = new AndroidPixelRef(env, info, (void*) addr,
bitmap->rowBytes(), arrayObj, ctable);
bitmap->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index 6ae9fea..c400c57 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -272,18 +272,11 @@ public:
float* dst = autoDst.ptr() + dstIndex;
bool result;
-#ifdef SK_SCALAR_IS_FIXED
- SkPoint srcPt[4], dstPt[4];
- for (int i = 0; i < ptCount; i++) {
- int x = i << 1;
- int y = x + 1;
- srcPt[i].set(SkFloatToScalar(src[x]), SkFloatToScalar(src[y]));
- dstPt[i].set(SkFloatToScalar(dst[x]), SkFloatToScalar(dst[y]));
- }
- result = matrix->setPolyToPoly(srcPt, dstPt, ptCount);
-#else
+#ifdef SK_SCALAR_IS_FLOAT
result = matrix->setPolyToPoly((const SkPoint*)src, (const SkPoint*)dst,
ptCount);
+#else
+ SkASSERT(false);
#endif
return result ? JNI_TRUE : JNI_FALSE;
}
@@ -304,36 +297,15 @@ public:
AutoJavaFloatArray autoDst(env, dst, dstIndex + (ptCount << 1), kRW_JNIAccess);
float* srcArray = autoSrc.ptr() + srcIndex;
float* dstArray = autoDst.ptr() + dstIndex;
-
-#ifdef SK_SCALAR_IS_FIXED
- // we allocate twice the count, 1 set for src, 1 for dst
- SkAutoSTMalloc<32, SkPoint> storage(ptCount * 2);
- SkPoint* pts = storage.get();
- SkPoint* srcPt = pts;
- SkPoint* dstPt = pts + ptCount;
-
- int i;
- for (i = 0; i < ptCount; i++) {
- srcPt[i].set(SkFloatToScalar(srcArray[i << 1]),
- SkFloatToScalar(srcArray[(i << 1) + 1]));
- }
-
- if (isPts)
- matrix->mapPoints(dstPt, srcPt, ptCount);
- else
- matrix->mapVectors(dstPt, srcPt, ptCount);
-
- for (i = 0; i < ptCount; i++) {
- dstArray[i << 1] = SkScalarToFloat(dstPt[i].fX);
- dstArray[(i << 1) + 1] = SkScalarToFloat(dstPt[i].fY);
- }
-#else
+#ifdef SK_SCALAR_IS_FLOAT
if (isPts)
matrix->mapPoints((SkPoint*)dstArray, (const SkPoint*)srcArray,
ptCount);
else
matrix->mapVectors((SkVector*)dstArray, (const SkVector*)srcArray,
ptCount);
+#else
+ SkASSERT(false);
#endif
}
@@ -356,18 +328,12 @@ public:
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
AutoJavaFloatArray autoValues(env, values, 9, kRW_JNIAccess);
float* dst = autoValues.ptr();
-
-#ifdef SK_SCALAR_IS_FIXED
- for (int i = 0; i < 6; i++) {
- dst[i] = SkFixedToFloat(matrix->get(i));
- }
- for (int j = 6; j < 9; j++) {
- dst[j] = SkFractToFloat(matrix->get(j));
- }
-#else
+#ifdef SK_SCALAR_IS_FLOAT
for (int i = 0; i < 9; i++) {
dst[i] = matrix->get(i);
}
+#else
+ SkASSERT(false);
#endif
}
@@ -376,17 +342,12 @@ public:
AutoJavaFloatArray autoValues(env, values, 9, kRO_JNIAccess);
const float* src = autoValues.ptr();
-#ifdef SK_SCALAR_IS_FIXED
- for (int i = 0; i < 6; i++) {
- matrix->set(i, SkFloatToFixed(src[i]));
- }
- for (int j = 6; j < 9; j++) {
- matrix->set(j, SkFloatToFract(src[j]));
- }
-#else
+#ifdef SK_SCALAR_IS_FLOAT
for (int i = 0; i < 9; i++) {
matrix->set(i, src[i]);
}
+#else
+ SkASSERT(false);
#endif
}
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 51990d5..1167bfe 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -422,16 +422,16 @@ public:
SkPaint::FontMetrics metrics;
GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
- int ascent = SkScalarRound(metrics.fAscent);
- int descent = SkScalarRound(metrics.fDescent);
- int leading = SkScalarRound(metrics.fLeading);
+ int ascent = SkScalarRoundToInt(metrics.fAscent);
+ int descent = SkScalarRoundToInt(metrics.fDescent);
+ int leading = SkScalarRoundToInt(metrics.fLeading);
if (metricsObj) {
SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class));
- env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloor(metrics.fTop));
+ env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloorToInt(metrics.fTop));
env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent);
env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent);
- env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeil(metrics.fBottom));
+ env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeilToInt(metrics.fBottom));
env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading);
}
return descent - ascent + leading;
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 144ac39..9279758 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -70,7 +70,7 @@ void TextLayoutCache::operator()(TextLayoutCacheKey& text, sp<TextLayoutValue>&
size_t totalSizeToDelete = text.getSize() + desc->getSize();
mSize -= totalSizeToDelete;
if (mDebugEnabled) {
- ALOGD("Cache value %p deleted, size = %d", desc.get(), totalSizeToDelete);
+ ALOGD("Cache value %p deleted, size = %zu", desc.get(), totalSizeToDelete);
}
}
@@ -130,7 +130,7 @@ sp<TextLayoutValue> TextLayoutCache::getValue(const SkPaint* paint,
bool removedOne = mCache.removeOldest();
LOG_ALWAYS_FATAL_IF(!removedOne, "The cache is non-empty but we "
"failed to remove the oldest entry. "
- "mSize = %u, size = %u, mMaxSize = %u, mCache.size() = %u",
+ "mSize = %u, size = %zu, mMaxSize = %u, mCache.size() = %zu",
mSize, size, mMaxSize, mCache.size());
}
}
@@ -149,7 +149,7 @@ sp<TextLayoutValue> TextLayoutCache::getValue(const SkPaint* paint,
nsecs_t totalTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
ALOGD("CACHE MISS: Added entry %p "
"with start = %d, count = %d, contextCount = %d, "
- "entry size %d bytes, remaining space %d bytes"
+ "entry size %zu bytes, remaining space %d bytes"
" - Compute time %0.6f ms - Put time %0.6f ms - Text = '%s'",
value.get(), start, count, contextCount, size, mMaxSize - mSize,
value->getElapsedTime() * 0.000001f,
@@ -160,7 +160,7 @@ sp<TextLayoutValue> TextLayoutCache::getValue(const SkPaint* paint,
if (mDebugEnabled) {
ALOGD("CACHE MISS: Calculated but not storing entry because it is too big "
"with start = %d, count = %d, contextCount = %d, "
- "entry size %d bytes, remaining space %d bytes"
+ "entry size %zu bytes, remaining space %d bytes"
" - Compute time %0.6f ms - Text = '%s'",
start, count, contextCount, size, mMaxSize - mSize,
value->getElapsedTime() * 0.000001f,
@@ -205,7 +205,7 @@ void TextLayoutCache::dumpCacheStats() {
ALOGD("------------------------------------------------");
ALOGD("pid : %d", getpid());
ALOGD("running : %.0f seconds", timeRunningInSec);
- ALOGD("entries : %d", cacheSize);
+ ALOGD("entries : %zu", cacheSize);
ALOGD("max size : %d bytes", mMaxSize);
ALOGD("used : %d bytes according to mSize", mSize);
ALOGD("remaining : %d bytes or %2.2f percent", mMaxSize - mSize, remainingPercent);
@@ -492,7 +492,7 @@ void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars,
(((ucs) & 0xfc00) == 0xdc00)
#ifndef HB_SurrogateToUcs4
-#define HB_SurrogateToUcs4_(high, low) \
+#define HB_SurrogateToUcs4(high, low) \
(((hb_codepoint_t)(high))<<10) + (low) - 0x35fdc00;
#endif
@@ -784,7 +784,7 @@ SkTypeface* TextLayoutShaper::typefaceForScript(const SkPaint* paint, SkTypeface
if (typeface) {
currentStyle = typeface->style();
}
- typeface = SkCreateTypefaceForScriptNG(script, currentStyle);
+ typeface = SkCreateTypefaceForScript(script, currentStyle);
#if DEBUG_GLYPHS
ALOGD("Using Harfbuzz Script %c%c%c%c, Style %d", HB_UNTAG(script), currentStyle);
#endif
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index 9f79f74..98f4bed 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -111,7 +111,7 @@ socket_bind_local (JNIEnv *env, jobject object, jobject fileDescriptor,
/* private native void listen_native(int fd, int backlog) throws IOException; */
static void
-socket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, int backlog)
+socket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, jint backlog)
{
int ret;
int fd;
@@ -231,7 +231,7 @@ java_opt_to_real(int optID, int* opt, int* level)
}
static jint
-socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, int optID)
+socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, jint optID)
{
int ret, value;
int opt, level;
@@ -279,7 +279,7 @@ socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, int optID)
}
static void socket_setOption(
- JNIEnv *env, jobject object, jobject fileDescriptor, int optID,
+ JNIEnv *env, jobject object, jobject fileDescriptor, jint optID,
jint boolValue, jint intValue) {
int ret;
int optname;
diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp
index 7cbbe12..59d6e41 100644
--- a/core/jni/android_nio_utils.cpp
+++ b/core/jni/android_nio_utils.cpp
@@ -37,7 +37,7 @@ void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) {
gNioJNI.getBasePointerID, buffer);
if (pointer != 0L) {
*array = NULL;
- return (void *) (jint) pointer;
+ return reinterpret_cast<void *>(pointer);
}
*array = (jarray) _env->CallStaticObjectMethod(gNioJNI.nioAccessClass,
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index a041693..d4873d6 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -800,7 +800,7 @@ static void dumpNativeHeap(FILE* fp)
fprintf(fp, "Total memory: %zu\n", totalMemory);
fprintf(fp, "Allocation records: %zd\n", recordCount);
if (backtraceSize != BACKTRACE_SIZE) {
- fprintf(fp, "WARNING: mismatched backtrace sizes (%d vs. %d)\n",
+ fprintf(fp, "WARNING: mismatched backtrace sizes (%zu vs. %d)\n",
backtraceSize, BACKTRACE_SIZE);
}
fprintf(fp, "\n");
@@ -823,7 +823,11 @@ static void dumpNativeHeap(FILE* fp)
if (backtrace[bt] == 0) {
break;
} else {
+#ifdef __LP64__
+ fprintf(fp, " %016x", backtrace[bt]);
+#else
fprintf(fp, " %08x", backtrace[bt]);
+#endif
}
}
fprintf(fp, "\n");
diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp
index 12beff7..7e12b1e 100644
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ b/core/jni/android_server_NetworkManagementSocketTagger.cpp
@@ -47,8 +47,8 @@ static jint QTagUid_tagSocketFd(JNIEnv* env, jclass,
return (jint)res;
}
-static int QTagUid_untagSocketFd(JNIEnv* env, jclass,
- jobject fileDescriptor) {
+static jint QTagUid_untagSocketFd(JNIEnv* env, jclass,
+ jobject fileDescriptor) {
int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
if (env->ExceptionOccurred() != NULL) {
diff --git a/core/jni/android_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
index d50a69f..6f7ee49 100644
--- a/core/jni/android_text_AndroidBidi.cpp
+++ b/core/jni/android_text_AndroidBidi.cpp
@@ -26,7 +26,7 @@
namespace android {
static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray,
- jbyteArray infoArray, int n, jboolean haveInfo)
+ jbyteArray infoArray, jint n, jboolean haveInfo)
{
// Parameters are checked on java side
// Failures from GetXXXArrayElements indicate a serious out-of-memory condition
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 8b85a7b7..94bd40f 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -51,7 +51,8 @@ static int directionality_map[U_CHAR_DIRECTION_COUNT] = {
namespace android {
-static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, jbyteArray destArray, int count)
+static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
+ jbyteArray destArray, jint count)
{
ScopedCharArrayRO src(env, srcArray);
if (src.get() == NULL) {
@@ -102,7 +103,7 @@ static jint getEastAsianWidth(JNIEnv* env, jobject obj, jchar input)
}
static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
- int start, int count, jbyteArray destArray)
+ jint start, jint count, jbyteArray destArray)
{
ScopedCharArrayRO src(env, srcArray);
if (src.get() == NULL) {
@@ -144,20 +145,20 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
}
}
-static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, int start, int count)
+static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, jint start, jint count)
{
ScopedCharArrayRW data(env, charArray);
if (data.get() == NULL) {
- return false;
+ return JNI_FALSE;
}
if (start < 0 || start > start + count
|| env->GetArrayLength(charArray) < start + count) {
jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
- return false;
+ return JNI_FALSE;
}
- bool ret = false;
+ jboolean ret = JNI_FALSE;
for (int i = start; i < start + count; i++) {
// XXX this thinks it knows that surrogates are never mirrored
@@ -166,7 +167,7 @@ static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, int start
if (c1 != c2) {
data[i] = c2;
- ret = true;
+ ret = JNI_TRUE;
}
}
return ret;
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index aa2c5f39..28a8a5d 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -117,7 +117,7 @@ static jlong android_text_format_Time_normalize(JNIEnv* env, jobject This,
time2java(env, This, t);
RELEASE_TIMEZONE(This, t)
- return result;
+ return static_cast<jlong>(result);
}
static void android_text_format_Time_switchTimezone(JNIEnv* env, jobject This,
@@ -155,7 +155,7 @@ static jint android_text_format_Time_compare(JNIEnv* env, jobject clazz,
RELEASE_TIMEZONE(aObject, a)
RELEASE_TIMEZONE(bObject, b)
- return result;
+ return static_cast<jint>(result);
}
static jstring android_text_format_Time_format2445(JNIEnv* env, jobject This)
@@ -346,7 +346,7 @@ static jlong android_text_format_Time_toMillis(JNIEnv* env, jobject This,
RELEASE_TIMEZONE(This, t)
- return result;
+ return static_cast<jlong>(result);
}
static void android_text_format_Time_set(JNIEnv* env, jobject This, jlong millis)
@@ -400,10 +400,10 @@ static jboolean android_text_format_Time_parse(JNIEnv* env, jobject This, jstrin
if (len < 8) {
jniThrowException(env, "android/util/TimeFormatException",
"String too short -- expected at least 8 characters.");
- return false;
+ return JNI_FALSE;
}
- jboolean inUtc = false;
+ jboolean inUtc = JNI_FALSE;
ScopedStringChars s(env, strObj);
@@ -414,49 +414,49 @@ static jboolean android_text_format_Time_parse(JNIEnv* env, jobject This, jstrin
n += get_char(env, s, 1, 100, &thrown);
n += get_char(env, s, 2, 10, &thrown);
n += get_char(env, s, 3, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_yearField, n);
// month
n = get_char(env, s, 4, 10, &thrown);
n += get_char(env, s, 5, 1, &thrown);
n--;
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_monField, n);
// day of month
n = get_char(env, s, 6, 10, &thrown);
n += get_char(env, s, 7, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_mdayField, n);
if (len > 8) {
// T
- if (!check_char(env, s, 8, 'T')) return false;
+ if (!check_char(env, s, 8, 'T')) return JNI_FALSE;
env->SetBooleanField(This, g_allDayField, JNI_FALSE);
// hour
n = get_char(env, s, 9, 10, &thrown);
n += get_char(env, s, 10, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_hourField, n);
// min
n = get_char(env, s, 11, 10, &thrown);
n += get_char(env, s, 12, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_minField, n);
// sec
n = get_char(env, s, 13, 10, &thrown);
n += get_char(env, s, 14, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_secField, n);
if (len > 15) {
// Z
- if (!check_char(env, s, 15, 'Z')) return false;
- inUtc = true;
+ if (!check_char(env, s, 15, 'Z')) return JNI_FALSE;
+ inUtc = JNI_TRUE;
}
} else {
env->SetBooleanField(This, g_allDayField, JNI_TRUE);
@@ -481,10 +481,10 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
if (len < 10) {
jniThrowException(env, "android/util/TimeFormatException",
"String too short --- expected at least 10 characters.");
- return false;
+ return JNI_FALSE;
}
- jboolean inUtc = false;
+ jboolean inUtc = JNI_FALSE;
ScopedStringChars s(env, strObj);
@@ -495,57 +495,57 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
n += get_char(env, s, 1, 100, &thrown);
n += get_char(env, s, 2, 10, &thrown);
n += get_char(env, s, 3, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_yearField, n);
// -
- if (!check_char(env, s, 4, '-')) return false;
+ if (!check_char(env, s, 4, '-')) return JNI_FALSE;
// month
n = get_char(env, s, 5, 10, &thrown);
n += get_char(env, s, 6, 1, &thrown);
--n;
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_monField, n);
// -
- if (!check_char(env, s, 7, '-')) return false;
+ if (!check_char(env, s, 7, '-')) return JNI_FALSE;
// day
n = get_char(env, s, 8, 10, &thrown);
n += get_char(env, s, 9, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_mdayField, n);
if (len >= 19) {
// T
- if (!check_char(env, s, 10, 'T')) return false;
+ if (!check_char(env, s, 10, 'T')) return JNI_FALSE;
env->SetBooleanField(This, g_allDayField, JNI_FALSE);
// hour
n = get_char(env, s, 11, 10, &thrown);
n += get_char(env, s, 12, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
int hour = n;
// env->SetIntField(This, g_hourField, n);
// :
- if (!check_char(env, s, 13, ':')) return false;
+ if (!check_char(env, s, 13, ':')) return JNI_FALSE;
// minute
n = get_char(env, s, 14, 10, &thrown);
n += get_char(env, s, 15, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
int minute = n;
// env->SetIntField(This, g_minField, n);
// :
- if (!check_char(env, s, 16, ':')) return false;
+ if (!check_char(env, s, 16, ':')) return JNI_FALSE;
// second
n = get_char(env, s, 17, 10, &thrown);
n += get_char(env, s, 18, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_secField, n);
// skip the '.XYZ' -- we don't care about subsecond precision.
@@ -579,32 +579,32 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
jniThrowExceptionFmt(env, "android/util/TimeFormatException",
"Unexpected character 0x%02x at position %d. Expected + or -",
c, tz_index);
- return false;
+ return JNI_FALSE;
}
- inUtc = true;
+ inUtc = JNI_TRUE;
if (offset != 0) {
if (len < tz_index + 6) {
jniThrowExceptionFmt(env, "android/util/TimeFormatException",
"Unexpected length; should be %d characters",
tz_index + 6);
- return false;
+ return JNI_FALSE;
}
// hour
n = get_char(env, s, tz_index + 1, 10, &thrown);
n += get_char(env, s, tz_index + 2, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
n *= offset;
hour += n;
// :
- if (!check_char(env, s, tz_index + 3, ':')) return false;
+ if (!check_char(env, s, tz_index + 3, ':')) return JNI_FALSE;
// minute
n = get_char(env, s, tz_index + 4, 10, &thrown);
n += get_char(env, s, tz_index + 5, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
n *= offset;
minute += n;
}
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 536a582..93dcbef 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -85,7 +85,7 @@ static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring
jboolean result = false;
if ((strlen(chars)+sizeof(LOG_NAMESPACE)) > PROPERTY_KEY_MAX) {
char buf2[200];
- snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %d characters\n",
+ snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %zu characters\n",
chars, PROPERTY_KEY_MAX - sizeof(LOG_NAMESPACE));
jniThrowException(env, "java/lang/IllegalArgumentException", buf2);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c5ab284..159ffb2 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -58,36 +58,11 @@ static struct {
jfieldID secure;
} gPhysicalDisplayInfoClassInfo;
-
-class ScreenshotPixelRef : public SkPixelRef {
-public:
- ScreenshotPixelRef(const SkImageInfo& info, ScreenshotClient* screenshot) :
- SkPixelRef(info),
- mScreenshot(screenshot) {
- setImmutable();
- }
-
- virtual ~ScreenshotPixelRef() {
- delete mScreenshot;
- }
-
-protected:
- // overrides from SkPixelRef
- virtual void* onLockPixels(SkColorTable** ct) {
- *ct = NULL;
- return (void*)mScreenshot->getPixels();
- }
-
- virtual void onUnlockPixels() {
- }
-
- SK_DECLARE_UNFLATTENABLE_OBJECT()
-private:
- ScreenshotClient* mScreenshot;
-
- typedef SkPixelRef INHERITED;
-};
-
+// Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
+void DeleteScreenshot(void* addr, void* context) {
+ SkASSERT(addr == ((ScreenshotClient*) context)->getPixels());
+ delete ((ScreenshotClient*) context);
+}
// ----------------------------------------------------------------------------
@@ -167,20 +142,19 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject display
}
}
- // takes ownership of ScreenshotClient
- ScreenshotPixelRef* pixels = new ScreenshotPixelRef(screenshotInfo, screenshot);
const ssize_t rowBytes =
screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
SkBitmap* bitmap = new SkBitmap();
bitmap->setConfig(screenshotInfo, (size_t)rowBytes);
if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) {
+ // takes ownership of ScreenshotClient
+ SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo,
+ (size_t) rowBytes, NULL, (void*) screenshot->getPixels(), &DeleteScreenshot,
+ (void*) screenshot);
+ pixels->setImmutable();
bitmap->setPixelRef(pixels)->unref();
bitmap->lockPixels();
- } else {
- // be safe with an empty bitmap.
- delete pixels;
- bitmap->setPixels(NULL);
}
return GraphicsJNI::createBitmap(env, bitmap,
diff --git a/core/res/res/drawable/btn_borderless_quantum.xml b/core/res/res/drawable/btn_borderless_quantum.xml
index 703fd11..2e3c515 100644
--- a/core/res/res/drawable/btn_borderless_quantum.xml
+++ b/core/res/res/drawable/btn_borderless_quantum.xml
@@ -15,5 +15,7 @@
-->
<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="?attr/colorButtonPressed"
- android:mask="@drawable/btn_qntm_alpha" />
+ android:tint="?attr/colorButtonPressed">
+ <item android:id="@id/mask"
+ android:drawable="@drawable/btn_qntm_alpha" />
+</touch-feedback>
diff --git a/core/res/res/drawable/btn_default_quantum.xml b/core/res/res/drawable/btn_default_quantum.xml
index 4cb8301..2919621 100644
--- a/core/res/res/drawable/btn_default_quantum.xml
+++ b/core/res/res/drawable/btn_default_quantum.xml
@@ -16,6 +16,8 @@
<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="?attr/colorButtonPressed">
- <nine-patch android:src="@drawable/btn_qntm_alpha"
- android:tint="?attr/colorButtonNormal" />
+ <item>
+ <nine-patch android:src="@drawable/btn_qntm_alpha"
+ android:tint="?attr/colorButtonNormal" />
+ </item>
</touch-feedback>
diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml b/core/res/res/drawable/notification_icon_legacy_bg.xml
index 4ac67c3..4ac67c3 100644
--- a/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml
+++ b/core/res/res/drawable/notification_icon_legacy_bg.xml
diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml b/core/res/res/drawable/notification_icon_legacy_bg_inset.xml
index 96c5573..96c5573 100644
--- a/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml
+++ b/core/res/res/drawable/notification_icon_legacy_bg_inset.xml
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_background.xml
index f33e2e3..7b508a9 100644
--- a/core/res/res/drawable/notification_quantum_background.xml
+++ b/core/res/res/drawable/notification_quantum_background.xml
@@ -17,5 +17,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffffff" />
- <corners android:radius="2dp" />
+ <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
</shape> \ No newline at end of file
diff --git a/core/res/res/layout/notification_quantum_action.xml b/core/res/res/layout/notification_quantum_action.xml
index 775182f..0986343 100644
--- a/core/res/res/layout/notification_quantum_action.xml
+++ b/core/res/res/layout/notification_quantum_action.xml
@@ -16,7 +16,7 @@
-->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
- style="?android:attr/borderlessButtonStyle"
+ style="@android:style/Widget.Quantum.Light.Button.Borderless.Small"
android:id="@+id/action0"
android:layout_width="0dp"
android:layout_height="48dp"
diff --git a/core/res/res/layout/notification_quantum_action_list.xml b/core/res/res/layout/notification_quantum_action_list.xml
index a8aef97..ec4919b 100644
--- a/core/res/res/layout/notification_quantum_action_list.xml
+++ b/core/res/res/layout/notification_quantum_action_list.xml
@@ -23,7 +23,7 @@
android:visibility="gone"
android:layout_marginBottom="8dp"
android:showDividers="middle"
- android:divider="?android:attr/listDivider"
+ android:divider="@drawable/list_divider_holo_light"
android:dividerPadding="12dp"
>
<!-- actions will be added here -->
diff --git a/core/res/res/layout/notification_quantum_action_tombstone.xml b/core/res/res/layout/notification_quantum_action_tombstone.xml
index 9104991..51e4205 100644
--- a/core/res/res/layout/notification_quantum_action_tombstone.xml
+++ b/core/res/res/layout/notification_quantum_action_tombstone.xml
@@ -16,7 +16,7 @@
-->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
- style="?android:attr/borderlessButtonStyle"
+ style="@android:style/Widget.Quantum.Light.Button.Borderless.Small"
android:id="@+id/action0"
android:layout_width="0dp"
android:layout_height="48dp"
diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml
index 3e97b2a..8863cfa 100644
--- a/core/res/res/layout/notification_template_quantum_base.xml
+++ b/core/res/res/layout/notification_template_quantum_base.xml
@@ -92,7 +92,7 @@
android:layout_height="12dp"
android:layout_marginStart="8dp"
android:visibility="gone"
- style="?android:attr/progressBarStyleHorizontal"
+ style="@style/Widget.Quantum.Light.ProgressBar.Horizontal"
/>
<LinearLayout
android:id="@+id/line3"
diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml
index d860045..63935bb 100644
--- a/core/res/res/layout/notification_template_quantum_big_base.xml
+++ b/core/res/res/layout/notification_template_quantum_big_base.xml
@@ -148,7 +148,7 @@
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:visibility="gone"
- style="?android:attr/progressBarStyleHorizontal"
+ style="@style/Widget.Quantum.Light.ProgressBar.Horizontal"
/>
</LinearLayout>
<ImageView
@@ -156,7 +156,7 @@
android:layout_height="1dp"
android:id="@+id/action_divider"
android:visibility="gone"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<include
layout="@layout/notification_quantum_action_list"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml
index 585be80..516b0c4 100644
--- a/core/res/res/layout/notification_template_quantum_big_text.xml
+++ b/core/res/res/layout/notification_template_quantum_big_text.xml
@@ -101,7 +101,7 @@
android:layout_marginEnd="8dp"
android:visibility="gone"
android:layout_weight="0"
- style="?android:attr/progressBarStyleHorizontal"
+ style="@style/Widget.Quantum.Light.ProgressBar.Horizontal"
/>
<TextView android:id="@+id/big_text"
android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
@@ -121,7 +121,7 @@
android:layout_height="1dip"
android:id="@+id/action_divider"
android:visibility="gone"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<include
layout="@layout/notification_quantum_action_list"
android:layout_width="match_parent"
@@ -135,7 +135,7 @@
android:id="@+id/overflow_divider"
android:layout_marginBottom="8dp"
android:visibility="visible"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<LinearLayout
android:id="@+id/line3"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml
index 31ed508..c6192be 100644
--- a/core/res/res/layout/notification_template_quantum_inbox.xml
+++ b/core/res/res/layout/notification_template_quantum_inbox.xml
@@ -103,7 +103,7 @@
android:layout_marginEnd="8dp"
android:visibility="gone"
android:layout_weight="0"
- style="?android:attr/progressBarStyleHorizontal"
+ style="@style/Widget.Quantum.Light.ProgressBar.Horizontal"
/>
<TextView android:id="@+id/inbox_text0"
android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
@@ -206,7 +206,7 @@
android:layout_height="1dip"
android:id="@+id/action_divider"
android:visibility="gone"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<include
layout="@layout/notification_quantum_action_list"
android:layout_width="match_parent"
@@ -218,7 +218,7 @@
android:layout_height="1dip"
android:id="@+id/overflow_divider"
android:visibility="visible"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<LinearLayout
android:id="@+id/line3"
android:layout_width="match_parent"
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 0d8c1f1..0e5a0e7 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -988,7 +988,7 @@
<string name="search_go" msgid="8298016669822141719">"ፍለጋ"</string>
<string name="searchview_description_search" msgid="6749826639098512120">"ፍለጋ"</string>
<string name="searchview_description_query" msgid="5911778593125355124">"ጥያቄ ፍለጋ"</string>
- <string name="searchview_description_clear" msgid="1330281990951833033">"ጥያቄ አጥራ"</string>
+ <string name="searchview_description_clear" msgid="1330281990951833033">"ጥያቄ አጽዳ"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"ጥያቄ አስረክብ"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"የድምፅ ፍለጋ"</string>
<string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"በመንካት አስስ ይንቃ?"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0cdaba8..999bc57 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4436,16 +4436,12 @@
<!-- Drawable used to show animated touch feedback. -->
<declare-styleable name="TouchFeedbackDrawable">
- <!-- The tint to use for feedback ripples. This attribute is mandatory. -->
+ <!-- The tint to use for feedback ripples. This attribute is required. -->
<attr name="tint" />
<!-- Specifies the Porter-Duff blending mode used to apply the tint. The default vlaue is src_atop, which draws over the opaque parts of the drawable. -->
<attr name="tintMode" />
<!-- Whether to pin feedback ripples to the center of the drawable. Default value is false. -->
<attr name="pinned" format="boolean" />
- <!-- Optional drawable used to mask ripple bounds before projection. -->
- <attr name="mask" format="reference" />
- <!-- Optional drawable onto which ripples are projected. -->
- <attr name="drawable" />
</declare-styleable>
<declare-styleable name="ScaleDrawable">
@@ -4541,6 +4537,145 @@
</declare-styleable>
<!-- ========================== -->
+ <!-- Vector drawable class -->
+ <!-- ========================== -->
+ <eat-comment />
+
+ <!-- Drawable used to draw Vector Drawables. -->
+ <declare-styleable name="VectorDrawable">
+ <!-- What event triggers the animation -->
+ <attr name="trigger" format="enum">
+ <enum name="state_pressed" value="1" />
+ <enum name="state_focused" value="2" />
+ <enum name="state_hovered" value="3" />
+ <enum name="state_selected" value="4" />
+ <enum name="state_checkable" value="5" />
+ <enum name="state_checked" value="6" />
+ <enum name="state_enabled" value="7" />
+ <enum name="state_activated" value="8" />
+ <enum name="state_window_focused" value="9" />
+ </attr>
+ </declare-styleable>
+
+ <!-- Define the virtual size of the drawing surface paths will draw to. -->
+ <declare-styleable name="VectorDrawableViewport">
+ <!-- The width of the canvas the drawing is on. -->
+ <attr name="viewportWidth" format="float"/>
+ <!-- The height of the canvas the drawing is on. -->
+ <attr name="viewportHeight" format="float"/>
+ </declare-styleable>
+
+ <!-- Define the size of the drawable -->
+ <declare-styleable name="VectorDrawableSize">
+ <!-- Width of the Vector Drawable. -->
+ <attr name="width" />
+ <!-- Height of the Vector Drawable. -->
+ <attr name="height" />
+ </declare-styleable>
+
+ <!-- Define the animations of drawable -->
+ <declare-styleable name="VectorDrawableAnimation">
+ <!-- Configures this animation sequence between the named paths -->
+ <attr name="sequence" format="string"/>
+ <!-- Limits an animation to only interpolate the selected variable -->
+ <attr name="limitTo" format="enum">
+ <enum name="unlimited" value="0"/>
+ <enum name="path" value="1"/>
+ <enum name="rotation" value="2"/>
+ <enum name="trimPathStart" value="3"/>
+ <enum name="trimPathEnd" value="4"/>
+ <enum name="trimPathOffset" value="5"/>
+ </attr>
+ <!-- Number of times to loop this aspect of the animation -->
+ <attr name="repeatCount"/>
+ <!-- A list of times in milliseconds to transision from on path to another.
+ List must contain one less than the number of named paths
+ e.g. given sequence="A,B,C,D" durations="100,0,100" implies 100ms for the
+ "A" to "B" transision instantanious switch to "C" and 100ms for "C" to "D". -->
+ <attr name="durations" format="string" />
+ <!-- The delay before stating this aspect of the animation in milli seconds -->
+ <attr name="startDelay" />
+ <!-- when repeating how does it repeat back and forth or a to b -->
+ <attr name="repeatStyle" format="enum">
+ <enum name="forward" value="0"/>
+ <enum name="reverse" value="1"/>[]
+ </attr>
+ <!-- how does the animation progress from start to finish -->
+ <attr name="animate" format="enum">
+ <enum name="linear" value="0"/>
+ <enum name="easeIn" value="1"/>
+ <enum name="easeOut" value="2"/>
+ <enum name="easeInOut" value="3"/>
+ </attr>
+ </declare-styleable>
+
+ <!-- Defines the path used in Vector Drawables. -->
+ <declare-styleable name="VectorDrawablePath">
+ <!-- The Name of this path -->
+ <attr name="name" />
+ <!-- The width a path stroke -->
+ <attr name="strokeWidth" format="float" />
+ <!-- The opacity of a path stroke -->
+ <attr name="strokeOpacity" format="float" />
+ <!-- The amount to rotate the path stroke -->
+ <attr name="rotation" />
+ <!-- The X coordinate of the center of rotation of a path -->
+ <attr name="pivotX" />
+ <!-- The Y coordinate of the center of rotation of a path -->
+ <attr name="pivotY" />
+ <!-- The color to stroke the path if not defined implies no stroke-->
+ <attr name="stroke" format="color" />
+ <!-- The color to fill the path if not defined implies no fill-->
+ <attr name="fill" format="color" />
+ <!-- The level of opacity of the filled area of the path -->
+ <attr name="fillOpacity" format="float" />
+ <!-- The specification of the operations that define the path -->
+ <attr name="pathData" format="string" />
+ <!-- The fraction of the path to trim from the start from 0 to 1 -->
+ <attr name="trimPathStart" format="float" />
+ <!-- The fraction of the path to trim from the end from 0 to 1 -->
+ <attr name="trimPathEnd" format="float" />
+ <!-- Shift trim region (allows visible region to include the start and end) from 0 to 1 -->
+ <attr name="trimPathOffset" format="float" />
+ <!-- Path will set the current clip path -->
+ <attr name="clipToPath" format="boolean" />
+ <!-- sets the linecap for a stroked path -->
+ <attr name="strokeLineCap" format="enum">
+ <enum name="butt" value="0"/>
+ <enum name="round" value="1"/>
+ <enum name="square" value="2"/>
+ </attr>
+ <!-- sets the lineJoin for a stroked path -->
+ <attr name="strokeLineJoin" format="enum">
+ <enum name="miter" value="0"/>
+ <enum name="round" value="1"/>
+ <enum name="bevel" value="2"/>
+ </attr>
+ <!-- sets the Miter limit for a stroked path -->
+ <attr name="strokeMiterLimit" format="float"/>
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_pressed" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_focused" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_selected" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_window_focused" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_enabled" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_activated" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_accelerated" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_hovered" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_checked" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_checkable" />
+ </declare-styleable>
+
+ <!-- ========================== -->
<!-- Animation class attributes -->
<!-- ========================== -->
<eat-comment />
@@ -5898,16 +6033,16 @@
<eat-comment />
<declare-styleable name="GlowPadView">
<!-- Reference to an array resource that be shown as targets around a circle. -->
- <attr name="targetDrawables"/>
+ <attr name="targetDrawables" format="reference" />
<!-- Reference to an array resource that be used as description for the targets around the circle. -->
- <attr name="targetDescriptions"/>
+ <attr name="targetDescriptions" format="reference" />
<!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
- <attr name="directionDescriptions"/>
+ <attr name="directionDescriptions" format="reference" />
<!-- Sets a drawable as the center. -->
- <attr name="handleDrawable"/>
+ <attr name="handleDrawable" format="reference" />
<!-- Drawable to use for wave ripple animation. -->
<attr name="outerRingDrawable" format="reference"/>
@@ -5919,22 +6054,22 @@
<attr name="innerRadius"/>
<!-- Outer radius of glow area. Target icons will be drawn on this circle. -->
- <attr name="outerRadius"/>
+ <attr name="outerRadius" format="dimension" />
<!-- Radius of glow under finger. -->
<attr name="glowRadius" format="dimension" />
<!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
- <attr name="vibrationDuration"/>
+ <attr name="vibrationDuration" format="integer" />
<!-- How close we need to be before snapping to a target. -->
- <attr name="snapMargin"/>
+ <attr name="snapMargin" format="dimension" />
<!-- Number of waves/chevrons to show in animation. -->
- <attr name="feedbackCount"/>
+ <attr name="feedbackCount" format="integer" />
<!-- Used when the handle shouldn't wait to be hit before following the finger -->
- <attr name="alwaysTrackFinger"/>
+ <attr name="alwaysTrackFinger" format="boolean" />
<!-- Location along the circle of the first item, in degrees.-->
<attr name="firstItemOffset" format="float" />
@@ -5951,45 +6086,6 @@
</declare-styleable>
<!-- =============================== -->
- <!-- MultiWaveView class attributes -->
- <!-- =============================== -->
- <eat-comment />
- <declare-styleable name="MultiWaveView">
- <!-- Reference to an array resource that be shown as targets around a circle. -->
- <attr name="targetDrawables" format="reference"/>
-
- <!-- Reference to an array resource that be used as description for the targets around the circle. -->
- <attr name="targetDescriptions" format="reference"/>
-
- <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
- <attr name="directionDescriptions" format="reference"/>
-
- <!-- Sets a drawable as the drag center. -->
- <attr name="handleDrawable" format="reference" />
-
- <!-- Drawables to use for chevron animations. May be null. -->
- <attr name="chevronDrawables" format="reference"/>
-
- <!-- Drawable to use for wave ripple animation. -->
- <attr name="waveDrawable" format="reference" />
-
- <!-- Outer radius of target circle. Icons will be drawn on this circle. -->
- <attr name="outerRadius" format="dimension" />
-
- <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
- <attr name="vibrationDuration" format="integer"/>
-
- <!-- How close we need to be before snapping to a target. -->
- <attr name="snapMargin" format="dimension" />
-
- <!-- Number of waves/chevrons to show in animation. -->
- <attr name="feedbackCount" format="integer" />
-
- <!-- Used when the handle shouldn't wait to be hit before following the finger -->
- <attr name="alwaysTrackFinger" format="boolean" />
- </declare-styleable>
-
- <!-- =============================== -->
<!-- SizeAdaptiveLayout class attributes -->
<!-- =============================== -->
<eat-comment />
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 1947c50..d0c455b 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -193,6 +193,9 @@
<drawable name="notification_template_icon_bg">#3333B5E5</drawable>
<drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
+ <color name="notification_icon_legacy_bg_color">#ff4285F4</color>
+ <color name="notification_action_legacy_color_filter">#ff555555</color>
+
<!-- Keyguard colors -->
<color name="keyguard_avatar_frame_color">#ffffffff</color>
<color name="keyguard_avatar_frame_shadow_color">#80000000</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4656f32..16af9a9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -950,7 +950,7 @@
<!-- Max space (in MB) allocated to DownloadManager to store the downloaded
files if they are to be stored in DownloadManager's data dir,
which typically is /data/data/com.android.providers.downloads/files -->
- <integer name="config_downloadDataDirSize">100</integer>
+ <integer name="config_downloadDataDirSize">200</integer>
<!-- Max number of downloads allowed to proceed concurrently -->
<integer name="config_MaxConcurrentDownloadsAllowed">5</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 8ec2e6f..94123a2 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -366,4 +366,7 @@
<!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
<dimen name="immersive_mode_cling_width">-1px</dimen>
+ <!-- radius of the corners of the quantum rounded rect background -->
+ <dimen name="notification_quantum_rounded_rect_radius">2dp</dimen>
+
</resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 56bb15f..a79e1fe 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -83,4 +83,5 @@
<item type="id" name="current_scene" />
<item type="id" name="scene_layoutid_cache" />
<item type="id" name="shared_element_name" />
+ <item type="id" name="mask" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d0dadf3..d4692f1 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2101,6 +2101,8 @@
=============================================================== -->
<eat-comment />
+ <public-padding type="attr" name="l_resource_pad" end="0x1010410" />
+
<public type="attr" name="fragmentBreadCrumbsStyle" />
<public type="attr" name="fastScrollStyle" />
<public type="attr" name="windowContentTransitions" />
@@ -2113,6 +2115,25 @@
<public type="attr" name="controlY2" />
<public type="attr" name="sharedElementName" />
<public type="attr" name="transitionGroup" />
+ <public type="attr" name="trigger" />
+ <public type="attr" name="viewportWidth" />
+ <public type="attr" name="viewportHeight" />
+ <public type="attr" name="fillOpacity" />
+ <public type="attr" name="fill" />
+ <public type="attr" name="pathData" />
+ <public type="attr" name="stroke" />
+ <public type="attr" name="strokeOpacity" />
+ <public type="attr" name="strokeWidth" />
+ <public type="attr" name="durations" />
+ <public type="attr" name="sequence" />
+ <public type="attr" name="repeatStyle" />
+ <public type="attr" name="trimPathStart" />
+ <public type="attr" name="trimPathEnd" />
+ <public type="attr" name="trimPathOffset" />
+ <public type="attr" name="strokeLineCap" />
+ <public type="attr" name="clipToPath" />
+ <public type="attr" name="animate" />
+ <public type="attr" name="limitTo" />
<public type="attr" name="requiredForProfile"/>
<public type="attr" name="pinned" />
<public type="attr" name="colorControlNormal" />
@@ -2122,10 +2143,17 @@
<public type="attr" name="colorButtonNormalColored" />
<public type="attr" name="colorButtonPressedColored" />
+ <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
+
<public type="dimen" name="recents_thumbnail_height" />
<public type="dimen" name="recents_thumbnail_width" />
+ <public-padding type="id" name="l_resource_pad" end="0x01020040" />
+
<public type="id" name="shared_element_name" />
+ <public type="id" name="mask" />
+
+ <public-padding type="style" name="l_resource_pad" end="0x01030200" />
<public type="style" name="Widget.Holo.FragmentBreadCrumbs" />
<public type="style" name="Widget.Holo.Light.FragmentBreadCrumbs" />
@@ -2324,4 +2352,19 @@
<public type="style" name="Widget.Quantum.Light.Button.Paper" />
<public type="style" name="Widget.Quantum.Light.Button.Paper.Color" />
+
+ <public type="style" name="TextAppearance.Quantum.Display4" />
+ <public type="style" name="TextAppearance.Quantum.Display3" />
+ <public type="style" name="TextAppearance.Quantum.Display2" />
+ <public type="style" name="TextAppearance.Quantum.Display1" />
+ <public type="style" name="TextAppearance.Quantum.Headline" />
+ <public type="style" name="TextAppearance.Quantum.Title" />
+ <public type="style" name="TextAppearance.Quantum.Subhead" />
+ <public type="style" name="TextAppearance.Quantum.Body2" />
+ <public type="style" name="TextAppearance.Quantum.Body1" />
+ <public type="style" name="TextAppearance.Quantum.Caption" />
+ <public type="style" name="TextAppearance.Quantum.Menu" />
+ <public type="style" name="TextAppearance.Quantum.Button" />
+
+ <public type="style" name="Widget.Holo.Light.Button.Borderless" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index efa873d..fa84750 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -346,6 +346,7 @@
<java-symbol type="dimen" name="notification_title_text_size" />
<java-symbol type="dimen" name="notification_subtext_size" />
<java-symbol type="dimen" name="immersive_mode_cling_width" />
+ <java-symbol type="dimen" name="notification_quantum_rounded_rect_radius" />
<java-symbol type="string" name="add_account_button_label" />
<java-symbol type="string" name="addToDictionary" />
@@ -1637,6 +1638,8 @@
<java-symbol type="layout" name="notification_template_quantum_big_picture" />
<java-symbol type="layout" name="notification_template_quantum_big_text" />
<java-symbol type="layout" name="notification_template_quantum_inbox" />
+ <java-symbol type="color" name="notification_action_legacy_color_filter" />
+ <java-symbol type="drawable" name="notification_icon_legacy_bg_inset" />
<!-- From SystemUI -->
<java-symbol type="anim" name="push_down_in" />
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 04f8009..e77564f 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -21,6 +21,7 @@ import static libcore.io.OsConstants.*;
import com.android.frameworks.coretests.R;
import com.android.internal.content.PackageHelper;
+import android.app.PackageInstallObserver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -31,6 +32,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
import android.os.IBinder;
@@ -117,12 +119,12 @@ public class PackageManagerTests extends AndroidTestCase {
super.tearDown();
}
- private class PackageInstallObserver extends IPackageInstallObserver.Stub {
+ private class TestInstallObserver extends PackageInstallObserver {
public int returnCode;
private boolean doneFlag = false;
- public void packageInstalled(String packageName, int returnCode) {
+ public void packageInstalled(String packageName, Bundle extras, int returnCode) {
synchronized (this) {
this.returnCode = returnCode;
doneFlag = true;
@@ -203,7 +205,7 @@ public class PackageManagerTests extends AndroidTestCase {
public void invokeInstallPackage(Uri packageURI, int flags, GenericReceiver receiver,
boolean shouldSucceed) {
- PackageInstallObserver observer = new PackageInstallObserver();
+ TestInstallObserver observer = new TestInstallObserver();
mContext.registerReceiver(receiver, receiver.filter);
try {
// Wait on observer
@@ -261,7 +263,7 @@ public class PackageManagerTests extends AndroidTestCase {
}
public void invokeInstallPackageFail(Uri packageURI, int flags, int expectedResult) {
- PackageInstallObserver observer = new PackageInstallObserver();
+ TestInstallObserver observer = new TestInstallObserver();
try {
// Wait on observer
synchronized (observer) {
diff --git a/docs/html/design/index.jd b/docs/html/design/index.jd
index 9ba32dd..7c7c5d9 100644
--- a/docs/html/design/index.jd
+++ b/docs/html/design/index.jd
@@ -1,4 +1,5 @@
page.title=Design
+page.viewport_width=970
header.hide=1
footer.hide=1
@jd:body
diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd
index 3f88b9d..eb28da8 100644
--- a/docs/html/develop/index.jd
+++ b/docs/html/develop/index.jd
@@ -1,5 +1,6 @@
fullpage=true
page.title=Develop
+page.viewport_width=970
header.hide=1
carousel=1
tabbedList=1
diff --git a/docs/html/distribute/index.jd b/docs/html/distribute/index.jd
index 544fdff..6c6e113 100644
--- a/docs/html/distribute/index.jd
+++ b/docs/html/distribute/index.jd
@@ -1,4 +1,5 @@
page.title=Distribute Apps
+page.viewport_width=970
header.hide=1
@jd:body
diff --git a/docs/html/index.jd b/docs/html/index.jd
index baeaa5b..99a469a 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -1,4 +1,5 @@
fullpage=true
+page.viewport_width=970
no_footer_links=true
carousel=true
excludeFromSuggestions=true
@@ -20,7 +21,7 @@ page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3
<li class="item carousel-home">
<div class="content-left col-10" style="width:580px;">
- <a href="{@docRoot}design/patterns/new.html">
+ <a href="{@docRoot}wear/index.html">
<img src="{@docRoot}images/home/aw_dac.png" style="margin-top:50px" >
</a>
</div>
diff --git a/docs/html/wear/design/index.html b/docs/html/wear/design/index.html
deleted file mode 100644
index 53ea1f3..0000000
--- a/docs/html/wear/design/index.html
+++ /dev/null
@@ -1,609 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Design Principles of Android Wear | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Design Principles of Android Wear</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <style>
-h3 {
- padding:30px 0 10px;
-}
-</style>
-<p>
-Android wearables provide just the right information at just the right time, allowing you to be connected to the virtual world and present in the real world.</p>
-
-<img src="/wear/images/05_images.png" height="200" width="169" style="float:right;clear:right;margin:0 0 60px 60px" />
-
-<p>Here you’ll find some guidelines for designing great user experiences on the Android Wear
-platform. Designing for Android Wear is substantially different than designing for phones or
-tablets, so we’ll start by describing how your content can work in tandem with the overall
-Android Wear vision. To better understand the user experience on Android Wear, also be sure
-to read the <a href="/wear/design/user-interface.html">UI Overview</a>.</p>
-
-
-<img src="/wear/images/02_notifications.png" height="200" width="169" style="float:right;clear:right;margin:0 0 20px 60px" />
-
-
-
-<p>Android Wear experiences are:</p>
-
-<ul>
- <li><strong>Contextually aware and smart.</strong> These devices bring a new level of awareness to computing. Rather than requiring attention and input from users, Android wearables are aware of their situation and state, and helpfully display the right information at the right time. <em>Timely, relevant, specific</em>.</li>
-
- <li><strong>Glanceable.</strong> Wearable devices are used all throughout the day, even when they sit in our peripheral vision. Effective apps provide the maximum payload of information with a minimum of fuss, optimized to provide tiny snippets of relevant information throughout the day. <em>Short, sharp, immediate.</em></li>
-
- <li><strong>Zero/low interaction.</strong> Staying true to the strengths afforded by a smaller form factor, Android Wear focuses on simple interactions, only requiring input by the user when absolutely necessary. Most inputs are based around touch swipes or voice, and inputs requiring fine-grained motor skills are avoided. <em>Gestural, simple, fast.</em></li>
-
- <li><strong>Helpful.</strong> Android Wear is like a great personal assistant: it knows you and your preferences, it only interrupts you when absolutely necessary, and it’s always on hand to provide a ready answer. <em>Efficient, respectful, responsive.</em></li>
-</ul>
-
-
-<p>
-By providing a smart connection to the rest of the world while respecting the user’s attention, Android Wear feels personal and global, simple and smart, unobtrusive and ever-ready. Notifications that respect these principles will feel most at home in the overall Android Wear experience.
-</p>
-
-
-
-<h2 id="Notifications" style="clear:both">Notification UI Patterns</h2>
-
-<p>Android notifications appear as cards in the main stream and form the core of the Android Wear experience. Many of the main <a href="http://developer.android.com/design/patterns/notifications.html">Android Design guidelines for notifications</a> apply in Android Wear. Be respectful of users' attention and aware of how unnecessary interruptions will reflect on your application’s reputation.</p>
-
-<p>Omit needless text from your notifications. Design for glanceability, not reading. Use words and phrases, not sentences. Show, don't tell: where possible use simple icons, glyphs, and visualizations to convey your message.</p>
-<img src="/wear/images/circle_message2.png" height="200" style="float:right;clear:right;margin:0 0 20px 60px" />
-
-<p>In some cases, particularly with messaging applications, cards will contain dynamic content which may not fit on a single screen. In these cases the content will be automatically truncated to fit on the card and the user may tap to expand, so the full message should be provided.</p>
-
-<p>Notification priority should reflect the urgency of your notification, with only time-sensitive notifications carrying a high priority. Active notifications – that is, those that cause the device to vibrate – should only be used in cases that need the user's urgent attention or action (e.g. a time-based reminder, a message from a friend). Non-urgent notifications (e.g. a transit times card, daily pedometer count, social network updates) should be silently added to the card stream.</p>
-
-
-
-
-<h3 id="NotifictionActions" style="clear:both">Actions</h3>
-
-<img src="/wear/images/circle_message2_reply.png" height="200" style="float:right;clear:right;margin:0 0 20px 40px" />
-
-<p>Actions appear to the right of your notification, allowing the user to act on your notification. Up to three actions are permitted. The most-used action should be placed first, so that it is a single swipe away from your content.</p>
-
-<p>Actions consist of an icon and a caption. Icons should be PNG files, white on transparent background, 32 × 32 dp (with 8 dp padding), as specified in the <a href="/design/style/iconography.html#action-bar">Iconography</a> design guide
-for the action bar icons. Captions should be verb-driven and short, and will be automatically truncated at one line.</p>
-
-<p>Actions are optional. Many useful notifications will not need to include actions at all.</p>
-
-<p>For developer details about action buttons, see <a href="/wear/notifications/creating.html">Creating
-Notifications for Android Wear</a>.</p>
-
-
-
-
-
-
-<h3 id="Images" style="clear:both">Images</h3>
-
-<img src="/wear/images/circle_badge_B.png" height="200" style="float:right;clear:right;margin:0 0 20px 40px" />
-
-
-<p>Images appear behind cards in the stream, providing context and additional glanceability. Your image should support the core message of the notification; for example, a card about a sports team could include the team color and logo; a message from a contact should display that person's profile photo.</p>
-
-<p>Bear in mind that the card will partially cover the lower part of the image. Images should be sized as
-appropriate for the notification appearance on handsets, which is 64 x 64 dp. Image backgrounds move when horizontally swiped, so landscape-oriented images work better on notifications that include pages or actions.</p>
-
-<p>To add large images, use <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setLargeIcon(android.graphics.Bitmap)">setLargeIcon()</a></code> with any notification, as
-shown in <a href="/wear/notifications/creating.html">Creating
-Notifications for Android Wear</a>.</p>
-
-
-
-
-
-<h3 id="AppIcons" style="clear:both">Application Icons</h3>
-
-<img src="/wear/images/07_appicons.png" height="200" style="float:right;margin:0 0 20px 60px" />
-
-<p>Your application’s launcher icon will be automatically placed on the card, identifying your notification. Do not use the notification title or background image to identify or brand your application. Instead, allow your icon to identify itself and focus on delivering a clear, succinct message in the card and image. You can choose not to display this icon using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setHintHideIcon(boolean)"><code>setHintHideIcon()</code></a>.
-</p>
-
-
-
-
-
-
-
-<h3 id="NotificationPages" style="clear:both">Pages</h3>
-
-<p>Pages are additional cards that can appear to the right of your main card in the stream. If your core message is longer than a short snippet, do not sacrifice glanceability by packing a lot of information into your primary notification. Instead, use pages to provide additional content.</p>
-
-<img src="/wear/images/08_pages.png" height="200" style="float:left;margin:0 0 20px 0px" />
-<img src="/wear/images/09_pages.png" height="200" style="float:left;margin:0 0 20px 60px" />
-<img src="/wear/images/10_pages.png" height="200" style="float:left;margin:0 0 20px 60px" />
-
-<p style="clear:left">Pages appear immediately to the right of the main notification card. They are typically used to provide additional details or alternate views of the main card’s content. For example:</p>
-<ul>
- <li>A current weather card might provide an additional page showing a three-day forecast.</li>
- <li>A next train departure card might provide an additional page showing subsequent departures times.</li>
- <li>A daily step count card might provide an additional page showing the same measurement in calories and distance.</li>
-</ul>
-
-<p>There is no imposed limit on the number of pages you may add. However, notifications that provide actions should show no more than three pages to ensure that the actions remain easily accessible.</p>
-
-<p>Pages are optional. Many useful notifications will not need to include pages at all.</p>
-
-<p>For developer details about pages, see
-described in <a href="/wear/notifications/pages.html">Adding
-Pages to a Notification</a>.</p>
-
-
-
-
-
-<h3 id="NotificationStacks" style="clear:both">Notification Stacks</h3>
-
-<img src="/wear/images/11_bundles_B.png" height="200" style="float:right;margin:0 0 20px 60px" />
-<img src="/wear/images/11_bundles_A.png" height="200" style="float:right;margin:0 0 20px 60px" />
-
-<p>Stacks may be used to collect multiple notifications from the same application into a single stack of cards. Whereas pages are used to provide additional detail on a single notification, stacks are used to collect multiple sibling notifications together. A stack may be expanded by the user to access each individual card contained within.</p>
-
-<p>Stacks are a way of adding multiple useful notifications without overwhelming the user’s stream. If your application may produce multiple concurrent notifications, consider combining them into a stack.</p>
-
-<p>Each notification within a stack can contain separate pages and separate actions that are relevant to that specific notification. The user can access these actions after expanding that notification's card within the stack.</p>
-
-<p>For developer details about stacks, see
-described in <a href="/wear/notifications/stacks.html">Stacking
-Notifications</a>.</p>
-
-
-
-
-
-
-<h3 id="VoiceReplies" style="clear:both">Voice Replies</h3>
-
-
-<img src="/wear/images/circle_voice_B.png" height="200" style="float:right;margin:0 0 20px 40px" />
-<img src="/wear/images/circle_voice_A.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>Voice replies are primarily used by messaging applications to provide a hands-free way of dictating a short message. You can also provide a up to five suggested replies or “canned responses” that are useful in a wide range of cases. These canned responses can be tapped by the user, allowing for a fast method of sending simple replies in cases where speaking may not be desirable.</p>
-
-<p>You should attempt to cover a range of simple, neutral replies in your choices. Longer voice replies may be automatically truncated in the Voice reply UI.</p>
-
-<p>For developer details about enabling voice replies, see
-described in <a href="/wear/notifications/remote-input.html">Receiving Voice Input from
-a Notification</a>.</p>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
- <a href="/legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/design/index.jd b/docs/html/wear/design/index.jd
new file mode 100644
index 0000000..247cc87
--- /dev/null
+++ b/docs/html/wear/design/index.jd
@@ -0,0 +1,173 @@
+page.title=Design Principles of Android Wear
+
+@jd:body
+
+<style>
+h3 {
+ padding:30px 0 10px;
+}
+</style>
+<p>
+Android wearables provide just the right information at just the right time, allowing you to be connected to the virtual world and present in the real world.</p>
+
+<img src="{@docRoot}wear/images/05_images.png" height="200" width="169" style="float:right;clear:right;margin:0 0 60px 60px" />
+
+<p>Here you’ll find some guidelines for designing great user experiences on the Android Wear
+platform. Designing for Android Wear is substantially different than designing for phones or
+tablets, so we’ll start by describing how your content can work in tandem with the overall
+Android Wear vision. To better understand the user experience on Android Wear, also be sure
+to read the <a href="{@docRoot}wear/design/user-interface.html">UI Overview</a>.</p>
+
+
+<img src="{@docRoot}wear/images/02_notifications.png" height="200" width="169" style="float:right;clear:right;margin:0 0 20px 60px" />
+
+
+
+<p>Android Wear experiences are:</p>
+
+<ul>
+ <li><strong>Contextually aware and smart.</strong> These devices bring a new level of awareness to computing. Rather than requiring attention and input from users, Android wearables are aware of their situation and state, and helpfully display the right information at the right time. <em>Timely, relevant, specific</em>.</li>
+
+ <li><strong>Glanceable.</strong> Wearable devices are used all throughout the day, even when they sit in our peripheral vision. Effective apps provide the maximum payload of information with a minimum of fuss, optimized to provide tiny snippets of relevant information throughout the day. <em>Short, sharp, immediate.</em></li>
+
+ <li><strong>Zero/low interaction.</strong> Staying true to the strengths afforded by a smaller form factor, Android Wear focuses on simple interactions, only requiring input by the user when absolutely necessary. Most inputs are based around touch swipes or voice, and inputs requiring fine-grained motor skills are avoided. <em>Gestural, simple, fast.</em></li>
+
+ <li><strong>Helpful.</strong> Android Wear is like a great personal assistant: it knows you and your preferences, it only interrupts you when absolutely necessary, and it’s always on hand to provide a ready answer. <em>Efficient, respectful, responsive.</em></li>
+</ul>
+
+
+<p>
+By providing a smart connection to the rest of the world while respecting the user’s attention, Android Wear feels personal and global, simple and smart, unobtrusive and ever-ready. Notifications that respect these principles will feel most at home in the overall Android Wear experience.
+</p>
+
+
+
+<h2 id="Notifications" style="clear:both">Notification UI Patterns</h2>
+
+<p>Android notifications appear as cards in the main stream and form the core of the Android Wear experience. Many of the main <a href="http://developer.android.com/design/patterns/notifications.html">Android Design guidelines for notifications</a> apply in Android Wear. Be respectful of users' attention and aware of how unnecessary interruptions will reflect on your application’s reputation.</p>
+
+<p>Omit needless text from your notifications. Design for glanceability, not reading. Use words and phrases, not sentences. Show, don't tell: where possible use simple icons, glyphs, and visualizations to convey your message.</p>
+<img src="{@docRoot}wear/images/circle_message2.png" height="200" style="float:right;clear:right;margin:0 0 20px 60px" />
+
+<p>In some cases, particularly with messaging applications, cards will contain dynamic content which may not fit on a single screen. In these cases the content will be automatically truncated to fit on the card and the user may tap to expand, so the full message should be provided.</p>
+
+<p>Notification priority should reflect the urgency of your notification, with only time-sensitive notifications carrying a high priority. Active notifications – that is, those that cause the device to vibrate – should only be used in cases that need the user's urgent attention or action (e.g. a time-based reminder, a message from a friend). Non-urgent notifications (e.g. a transit times card, daily pedometer count, social network updates) should be silently added to the card stream.</p>
+
+
+
+
+<h3 id="NotifictionActions" style="clear:both">Actions</h3>
+
+<img src="{@docRoot}wear/images/circle_message2_reply.png" height="200" style="float:right;clear:right;margin:0 0 20px 40px" />
+
+<p>Actions appear to the right of your notification, allowing the user to act on your notification. Up to three actions are permitted. The most-used action should be placed first, so that it is a single swipe away from your content.</p>
+
+<p>Actions consist of an icon and a caption. Icons should be PNG files, white on transparent
+background, 32 × 32 dp (with 8 dp padding), as specified in the <a
+href="/design/style/iconography.html#action-bar">Iconography</a> design guide for action bar
+icons. Captions should be verb-driven and short, and will be automatically truncated at one line.
+</p>
+
+<p>Actions are optional. Many useful notifications will not need to include actions at all.</p>
+
+<p>For developer details about action buttons, see <a href="{@docRoot}wear/notifications/creating.html">Creating
+Notifications for Android Wear</a>.</p>
+
+
+
+
+
+
+<h3 id="Images" style="clear:both">Images</h3>
+
+<img src="{@docRoot}wear/images/circle_badge_B.png" height="200" style="float:right;clear:right;margin:0 0 20px 40px" />
+
+
+<p>Images appear behind cards in the stream, providing context and additional glanceability. Your image should support the core message of the notification; for example, a card about a sports team could include the team color and logo; a message from a contact should display that person's profile photo.</p>
+
+<p>Bear in mind that the card will partially cover the lower part of the image. Images should
+be sized as appropriate for the notification appearance on handsets, which is 64 x 64 dp. Image backgrounds move when horizontally swiped, so landscape-oriented images work better on notifications that include pages or actions.</p>
+
+<p>To add large images, use {@link android.support.v4.app.NotificationCompat.Builder#setLargeIcon
+setLargeIcon()} with any notification, as
+shown in <a href="{@docRoot}wear/notifications/creating.html">Creating
+Notifications for Android Wear</a>.</p>
+
+
+
+
+
+<h3 id="AppIcons" style="clear:both">Application Icons</h3>
+
+<img src="{@docRoot}wear/images/07_appicons.png" height="200" style="float:right;margin:0 0 20px 60px" />
+
+<p>Your application’s launcher icon will be automatically placed on the card, identifying your notification. Do not use the notification title or background image to identify or brand your application. Instead, allow your icon to identify itself and focus on delivering a clear, succinct message in the card and image. You can choose not to display this icon using
+ <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setHintHideIcon(boolean)"><code>setHintHideIcon()</code></a>.
+</p>
+
+
+
+
+
+
+
+<h3 id="NotificationPages" style="clear:both">Pages</h3>
+
+<p>Pages are additional cards that can appear to the right of your main card in the stream. If your core message is longer than a short snippet, do not sacrifice glanceability by packing a lot of information into your primary notification. Instead, use pages to provide additional content.</p>
+
+<img src="{@docRoot}wear/images/08_pages.png" height="200" style="float:left;margin:0 0 20px 0px" />
+<img src="{@docRoot}wear/images/09_pages.png" height="200" style="float:left;margin:0 0 20px 60px" />
+<img src="{@docRoot}wear/images/10_pages.png" height="200" style="float:left;margin:0 0 20px 60px" />
+
+<p style="clear:left">Pages appear immediately to the right of the main notification card. They are typically used to provide additional details or alternate views of the main card’s content. For example:</p>
+<ul>
+ <li>A current weather card might provide an additional page showing a three-day forecast.</li>
+ <li>A next train departure card might provide an additional page showing subsequent departures times.</li>
+ <li>A daily step count card might provide an additional page showing the same measurement in calories and distance.</li>
+</ul>
+
+<p>There is no imposed limit on the number of pages you may add. However, notifications that provide actions should show no more than three pages to ensure that the actions remain easily accessible.</p>
+
+<p>Pages are optional. Many useful notifications will not need to include pages at all.</p>
+
+<p>For developer details about pages, see
+described in <a href="{@docRoot}wear/notifications/pages.html">Adding
+Pages to a Notification</a>.</p>
+
+
+
+
+
+<h3 id="NotificationStacks" style="clear:both">Notification Stacks</h3>
+
+<img src="{@docRoot}wear/images/11_bundles_B.png" height="200" style="float:right;margin:0 0 20px 60px" />
+<img src="{@docRoot}wear/images/11_bundles_A.png" height="200" style="float:right;margin:0 0 20px 60px" />
+
+<p>Stacks may be used to collect multiple notifications from the same application into a single stack of cards. Whereas pages are used to provide additional detail on a single notification, stacks are used to collect multiple sibling notifications together. A stack may be expanded by the user to access each individual card contained within.</p>
+
+<p>Stacks are a way of adding multiple useful notifications without overwhelming the user’s stream. If your application may produce multiple concurrent notifications, consider combining them into a stack.</p>
+
+<p>Each notification within a stack can contain separate pages and separate actions that are relevant to that specific notification. The user can access these actions after expanding that notification's card within the stack.</p>
+
+<p>For developer details about stacks, see
+described in <a href="{@docRoot}wear/notifications/stacks.html">Stacking
+Notifications</a>.</p>
+
+
+
+
+
+
+<h3 id="VoiceReplies" style="clear:both">Voice Replies</h3>
+
+
+<img src="{@docRoot}wear/images/circle_voice_B.png" height="200" style="float:right;margin:0 0 20px 40px" />
+<img src="{@docRoot}wear/images/circle_voice_A.png" height="200" style="float:right;margin:0 0 20px 40px" />
+
+<p>Voice replies are primarily used by messaging applications to provide a hands-free way of dictating a short message. You can also provide a up to five suggested replies or “canned responses” that are useful in a wide range of cases. These canned responses can be tapped by the user, allowing for a fast method of sending simple replies in cases where speaking may not be desirable.</p>
+
+<p>You should attempt to cover a range of simple, neutral replies in your choices. Longer voice replies may be automatically truncated in the Voice reply UI.</p>
+
+<p>For developer details about enabling voice replies, see
+described in <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from
+a Notification</a>.</p>
diff --git a/docs/html/wear/design/user-interface.html b/docs/html/wear/design/user-interface.html
deleted file mode 100644
index c23d79c..0000000
--- a/docs/html/wear/design/user-interface.html
+++ /dev/null
@@ -1,498 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>UI Overview | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<link rel="stylesheet" type="text/css" href="/wear/css/wear.css">
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >UI Overview</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <style>
-h3 {
- padding:30px 0 10px;
-}
-</style>
-
-<p>A new form factor deserves a new UI model. At a high level, the Android Wear UI consists of two
-main spaces centered around the core functions of <strong>Suggest</strong> and
-<strong>Demand</strong>. Your application will have an important role to play in both of these
-spaces.</p>
-
-
-
-<h3 id="Stream">Suggest: The Context Stream</h3>
-
-<div class="wear-inset-video-container" style="float:right;margin:0 -22px 60px 40px">
- <img class="wear-bezel-only" src="/wear/images/screens/bezel.png" alt="">
- <img class="gif" src="/wear/images/screens/stream.gif">
-</div>
-
-<p>The context stream is a vertical list of cards, each showing a useful or timely piece of
-information. Much like Google Now on Android phones and tablets, users swipe vertically to navigate
-from card to card for a brief and comprehensive update about what's important to them. Only one card
-is displayed on screen at a time, and background images are used to provide additional visual
-information. Your application can create cards and inject them into the stream when they are most
-likely to be useful.</p>
-
-<p>Cards in the stream are more than simple notifications. They can be swiped horizontally to
-reveal additional pages. Further horizontal swiping may reveal tappable buttons, allowing the user
-to take action on the notification. Cards can also be dismissed by swiping left to right, removing
-them from the stream until the next time they have useful information to display.
-In the emulator, hovering the mouse over the top of the screen illuminates a blue bar at
-the top of the device that takes you home when clicked.</p>
-
-
-
-<h3 id="CueCard">Demand: The Cue Card</h3>
-
-<div class="wear-inset-video-container" style="float:right;margin:0 -22px 60px 40px">
- <img class="wear-bezel-only" src="/wear/images/screens/bezel.png" alt="">
- <img class="gif" src="/wear/images/screens/cuecard.gif">
-</div>
-
-<p>For cases where the context stream can't anticipate what the user would like to do, the cue card
-allows users to speak to their device. The cue card is opened by saying, "Ok Google" or by tapping
-on the "g" icon on the home screen. Swiping up on the cue card shows a list of actions, which can
-also be tapped.</p>
-
-<p>The list of actions includes Android intents for voice actions. The upcoming Android Wear SDK
-will enable developers to match their applications to these intents so users can perform actions
-using these voice commands. Multiple applications may register for a single voice intent, and users
-will have the opportunity to choose which application they prefer to use.</p>
-
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
- <a href="/legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/design/user-interface.jd b/docs/html/wear/design/user-interface.jd
new file mode 100644
index 0000000..2a3e9ef
--- /dev/null
+++ b/docs/html/wear/design/user-interface.jd
@@ -0,0 +1,58 @@
+page.title=UI Overview
+page.customHeadTag=<link rel="stylesheet" type="text/css" href="/wear/css/wear.css">
+
+@jd:body
+
+<style>
+h3 {
+ padding:30px 0 10px;
+}
+</style>
+
+<p>A new form factor deserves a new UI model. At a high level, the Android Wear UI consists of two
+main spaces centered around the core functions of <strong>Suggest</strong> and
+<strong>Demand</strong>. Your application will have an important role to play in both of these
+spaces.</p>
+
+
+
+<h3 id="Stream">Suggest: The Context Stream</h3>
+
+<div class="wear-inset-video-container" style="float:right;margin:0 -22px 60px 40px">
+ <img class="wear-bezel-only" src="{@docRoot}wear/images/screens/bezel.png" alt="">
+ <img class="gif" src="{@docRoot}wear/images/screens/stream.gif">
+</div>
+
+<p>The context stream is a vertical list of cards, each showing a useful or timely piece of
+information. Much like Google Now on Android phones and tablets, users swipe vertically to navigate
+from card to card for a brief and comprehensive update about what's important to them. Only one card
+is displayed on screen at a time, and background images are used to provide additional visual
+information. Your application can create cards and inject them into the stream when they are most
+likely to be useful.</p>
+
+<p>Cards in the stream are more than simple notifications. They can be swiped horizontally to
+reveal additional pages. Further horizontal swiping may reveal tappable buttons, allowing the user
+to take action on the notification. Cards can also be dismissed by swiping left to right, removing
+them from the stream until the next time they have useful information to display.
+In the emulator, hovering the mouse over the top of the screen illuminates a blue bar at
+the top of the device that takes you home when clicked.</p>
+
+
+
+<h3 id="CueCard">Demand: The Cue Card</h3>
+
+<div class="wear-inset-video-container" style="float:right;margin:0 -22px 60px 40px">
+ <img class="wear-bezel-only" src="{@docRoot}wear/images/screens/bezel.png" alt="">
+ <img class="gif" src="{@docRoot}wear/images/screens/cuecard.gif">
+</div>
+
+<p>For cases where the context stream can't anticipate what the user would like to do, the cue card
+allows users to speak to their device. The cue card is opened by saying, "Ok Google" or by tapping
+on the "g" icon on the home screen. Swiping up on the cue card shows a list of actions, which can
+also be tapped.</p>
+
+<p>The list of actions includes Android intents for voice actions. The upcoming Android Wear SDK
+will enable developers to match their applications to these intents so users can perform actions
+using these voice commands. Multiple applications may register for a single voice intent, and users
+will have the opportunity to choose which application they prefer to use.</p>
+
diff --git a/docs/html/wear/index.html b/docs/html/wear/index.jd
index 9660463..a6a6460 100644
--- a/docs/html/wear/index.html
+++ b/docs/html/wear/index.jd
@@ -1,286 +1,12 @@
-<!DOCTYPE html>
+page.title=Android Wear
+page.viewport_width=970
+fullpage=true
+no_footer_links=true
+page.customHeadTag=<link rel="stylesheet" type="text/css" href="/wear/css/wear.css">
+@jd:body
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=970" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Android Wear | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<link rel="stylesheet" type="text/css" href="/wear/css/wear.css">
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div id="body-content">
-
-
-
-
-<div class="fullpage" >
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <style>
+<style>
.fullpage>#footer,
#jd-content>.content-footer.wrap {
display:none;
@@ -471,10 +197,10 @@ $("#icon-video-close").on("click", function() {
</div>
<p>
- You can also trigger your notifications contextually using existing Android APIs. For example, use <a href="/training/location/geofencing.html">geofences</a> to provide glanceable information to your users when they are at home, or use the <a href="/training/location/activity-recognition.html">activity detection APIs</a> to send messages to your users’ wrists while they are bicycling.
+ You can also trigger your notifications contextually using existing Android APIs. For example, use <a href="{@docRoot}training/location/geofencing.html">geofences</a> to provide glanceable information to your users when they are at home, or use the <a href="{@docRoot}training/location/activity-recognition.html">activity detection APIs</a> to send messages to your users’ wrists while they are bicycling.
</p>
- <p>See the <a href="/wear/design/index.html">Android Wear Developer Preview Design Principles</a> for more suggestions on creating great wearable experiences.</p>
+ <p>See the <a href="{@docRoot}wear/design/index.html">Android Wear Developer Preview Design Principles</a> for more suggestions on creating great wearable experiences.</p>
</div>
</div> <!-- end .wrap -->
@@ -677,63 +403,3 @@ $("#icon-video-close").on("click", function() {
});
</script>
-
- </div>
-
- <div class="content-footer wrap"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-16" style="padding-top:4px">
- <style>#___plusone_0 {float:right !important;}</style>
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" style="width:940px">
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/license.html b/docs/html/wear/license.jd
index c7569bc..b07dacf 100644
--- a/docs/html/wear/license.html
+++ b/docs/html/wear/license.jd
@@ -1,379 +1,9 @@
-<!DOCTYPE html>
+page.title=Developer Preview License Agreement
+@jd:body
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Developer Preview License Agreement | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Developer Preview License Agreement</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <div class="sdk-terms" style="height:auto;border:0;padding:0;width:700px">
+<div class="sdk-terms" style="height:auto;border:0;padding:0;width:700px">
This is the Android Wear Developer Preview License Agreement.
1. Introduction
@@ -510,72 +140,3 @@ This is the Android Wear Developer Preview License Agreement.
14.7 This License Agreement, and your relationship with Google under this License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from this License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
</div>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
- <a href="/legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/creating.html b/docs/html/wear/notifications/creating.html
deleted file mode 100644
index 7ad6833..0000000
--- a/docs/html/wear/notifications/creating.html
+++ /dev/null
@@ -1,722 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Creating Notifications for Android Wear | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Creating Notifications for Android Wear</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <p>When an Android device such as a phone or tablet is connected to an Android wearable,
-all notifications are shared between the devices by default. On the Android wearable, each
-notification appears as a new card in the <a href="/wear/design/user-interface.html#Stream"
->context stream</a>.</p>
-
-<img src="/wear/images/notification_phone@2x.png" width="700" height="265" />
-
-
-<p>So without any effort, your app notifications are available to users on Android Wear.
-However, you can enhance the user experience in several ways. For instance,
-if users may respond to a notification by entering text, such as to reply to
-a message, you can add the ability for users to reply by voice directly from the
-wearable.</p>
-
-<p>To help you provide the best user experience
-for your notifications on Android Wear, this guide shows you how to
-build notifications using standard templates in
-the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html">NotificationCompat.Builder</a></code> APIs, plus how to begin
-extending your notification's capabilities for the wearable user experience.</p>
-
-<p class="note"><strong>Note:</strong>
-Notifications using <code><a href="/reference/android/widget/RemoteViews.html">RemoteViews</a></code> are stripped of custom
-layouts and the system uses only the text and icons in the
-<code><a href="/reference/android/app/Notification.html">Notification</a></code> object to
-display the notification in a card. However, custom card layouts will be supported by
-the official Android Wear SDK that is coming later.</p>
-</div>
-
-
-
-
-<h2 id="Import">Import the Necessary Classes</h2>
-
-<p>To begin development, you must first complete the instructions in the <a
-href="/wear/preview/start">Get Started with the Developer Preview</a> document.
-As mentioned in that document, your app must include
-both the <a href="http://developer.android.com/tools/support-library/features.html#v4">v4 support
-library</a> and the Developer Preview support library. So to get started,
-you should include the following imports in your project code:</p>
-
-<pre>
-import android.preview.support.wearable.notifications.*;
-import android.preview.support.v4.app.NotificationManagerCompat;
-import android.support.v4.app.NotificationCompat;
-</pre>
-
-<p class="caution"><strong>Caution:</strong>
-The APIs in the current Android Wear Developer Preview are intended for <b>development and testing purposes only</b>, not for production apps. Google may change this Developer Preview significantly prior to the official release of the Android Wear SDK. You may not publicly distribute or ship any application using this Developer Preview, as this Developer Preview will no longer be supported after the official SDK is released (which will cause applications based only on the Developer Preview to break).</p>
-
-
-
-<h2 id="NotificationBuilder">Create Notifications with the Notification Builder</h2>
-
-<p>The <a href="http://developer.android.com/tools/support-library/features.html#v4">v4
-support library</a> allows you to create notifications using the latest notification features
-such as action buttons and large icons, while remaining compatible with Android 1.6 (API level
-4) and higher.</p>
-
-
-<p>For example, here's some code that creates and issues a notification using the
-<code><a href="/reference/android/support/v4/app/NotificationCompat.html">NotificationCompat</a></code> APIs combined with the new
-<a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">
-<code>NotificationManagerCompat</code></a> API:</p>
-
-
-<pre>
-int notificationId = 001;
-// Build intent for notification content
-Intent viewIntent = new Intent(this, ViewEventActivity.class);
-viewIntent.putExtra(EXTRA_EVENT_ID, eventId);
-PendingIntent viewPendingIntent =
- PendingIntent.getActivity(this, 0, viewIntent, 0);
-
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.ic_event)
- .setContentTitle(eventTitle)
- .setContentText(eventLocation)
- .setContentIntent(viewPendingIntent);
-
-// Get an instance of the NotificationManager service
-NotificationManagerCompat notificationManager =
- NotificationManagerCompat.from(this);
-
-// Build the notification and issues it with notification manager.
-notificationManager.notify(notificationId, notificationBuilder.build());
-</pre>
-
-<p>When this notification appears on a handheld device, the user can invoke the
-<code><a href="/reference/android/app/PendingIntent.html">PendingIntent</a></code>
-specified by the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)">setContentIntent()</a></code> method by touching the notification. When this
-notification appears on an Android wearable, the user can swipe the notification to the left to
-reveal the <strong>Open</strong> action, which invokes the intent on the handheld device.</p>
-
-
-
-
-
-
-<img src="/wear/images/circle_email_action.png" height="200" style="float:right;clear:right;margin:0 0 20px 60px" />
-
-<h2 id="ActionButtons">Add Action Buttons</h2>
-
-<p>In addition to the primary content action defined by
-<code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)">setContentIntent()</a></code>, you can add other actions by passing a <code><a href="/reference/android/app/PendingIntent.html">PendingIntent</a></code> to
-the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#addAction(int, java.lang.CharSequence, android.app.PendingIntent)">addAction()</a></code> method.</p>
-
-<p>For example, the following code shows the same type of notification from above, but adds an
-action to view the event location on a map.</p>
-
-<pre style="clear:right">
-// Build an intent for an action to view a map
-Intent mapIntent = new Intent(Intent.ACTION_VIEW);
-Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location));
-mapIntent.setData(geoUri);
-PendingIntent mapPendingIntent =
- PendingIntent.getActivity(this, 0, mapIntent, 0);
-
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.ic_event)
- .setContentTitle(eventTitle)
- .setContentText(eventLocation)
- .setContentIntent(viewPendingIntent)
- <b>.addAction(R.drawable.ic_map,
- getString(R.string.map), mapPendingIntent);</b>
-</pre>
-
-<p>On a handheld device, the action appears as an
-additional button attached to the notification. On an Android wearable, the action appears as
-a large button when the user swipes the notification to the left. When the user taps the action,
-the associated <code><a href="/reference/android/content/Intent.html">Intent</a></code> is invoked on the handheld device.</p>
-
-<p class="note"><strong>Tip:</strong> If your notifications includes a "Reply" action
- (such as for a messaging app), you can enhance the behavior by enabling
- voice input replies directly from the Android wearable. For more information, read
- <a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification</a>.
-</p>
-
-<p>For details about designing action buttons (including the icon specifications), see the
-<a href="/wear/design/index.html#NotifictionActions">Design Principles of Android
-Wear</a>.</p>
-
-
-<h2 id="BigView">Add a Big View</h2>
-
-<img src="/wear/images/06_images.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>You can insert extended text content
-to your notification by adding one of the "big view" styles to your notification. On a
-handheld device, users can see the big view content by expanding the notification,
-while on Android Wear, the big view content is visible by default.</p>
-
-<p>To add the extended content to your notification, call <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setStyle(android.support.v4.app.NotificationCompat.Style)">setStyle()</a></code> on the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html">NotificationCompat.Builder</a></code> object, passing it an instance of either
-<code><a href="/reference/android/support/v4/app/NotificationCompat.BigTextStyle.html">BigTextStyle</a></code> or
-<code><a href="/reference/android/support/v4/app/NotificationCompat.InboxStyle.html">InboxStyle</a></code>.</p>
-
-<p>For example, the following code adds an instance of
-<code><a href="/reference/android/support/v4/app/NotificationCompat.BigTextStyle.html">NotificationCompat.BigTextStyle</a></code> to the event notification,
-in order to include the complete event description (which includes more text than can fit
-into the space provided for <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentText(java.lang.CharSequence)">setContentText()</a></code>).</p>
-
-
-<pre style="clear:right">
-// Specify the 'big view' content to display the long
-// event description that may not fit the normal content text.
-BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
-bigStyle.bigText(eventDescription);
-
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.ic_event)
- .setLargeIcon(BitmapFractory.decodeResource(
- getResources(), R.drawable.notif_background))
- .setContentTitle(eventTitle)
- .setContentText(eventLocation)
- .setContentIntent(viewPendingIntent)
- .addAction(R.drawable.ic_map,
- getString(R.string.map), mapPendingIntent)
- <b>.setStyle(bigStyle);</b>
-</pre>
-
-<p>Notice that you can add a large background image to any notification using the
-<code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setLargeIcon(android.graphics.Bitmap)">setLargeIcon()</a></code>
-method. For more information about designing notifications with large images, see the
-<a href="/wear/design/index.html#Images">Design Principles of Android
-Wear</a>.</p>
-
-
-
-<h2 id="NewFeatures">Add New Features for Wearables</h2>
-
-<p>The Android Wear preview support library provides new APIs that
- allow you to enhance the user experience for notifications on a wearable device. For example,
- you can add additional pages of content that users can view by swiping to the left, or add the ability
-for users to deliver your app a text response using voice input.</p>
-
-<p>To use these new APIs, pass your instance of
-<code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html">NotificationCompat.Builder</a></code> to the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#WearableNotifications.Builder(android.content.Context)"> <code>WearableNotifications.Builder()</code></a> constructor. You can then add new
-features to your notification using the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
- ><code>WearableNotifications.Builder</code></a> methods. For example:</p>
-
-<pre>
-// Create a NotificationCompat.Builder for standard notification features
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(mContext)
- .setContentTitle("New mail from " + sender.toString())
- .setContentText(subject)
- .setSmallIcon(R.drawable.new_mail);
-
-// Create a WearablesNotification.Builder to add special functionality for wearables
-Notification notification =
- new WearableNotifications.Builder(notificationBuilder)
- .setHintHideIcon(true)
- .build();
-</pre>
-
-<p>The <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setBigActionIcon(int)">
- <code>setHintHideIcon()</code></a> method removes your app icon from the notification card.
- This method is just one example of new notification features available from the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
- ><code>WearableNotifications.Builder</code></a> class.</p>
-
-<p>When you want to deliver your notifications, be certain to always use the
- <a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">
- <code>NotificationManagerCompat</code></a> API:</p>
-
-<pre>
-// Get an instance of the NotificationManager service
-NotificationManagerCompat notificationManager =
- NotificationManagerCompat.from(this);
-
-// Build the notification and issues it with notification manager.
-notificationManager.notify(notificationId, notification);
-</pre>
-
-<p>If you instead use the framework's <code><a href="/reference/android/app/NotificationManager.html">NotificationManager</a></code>, some
-features from <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"><code>WearableNotifications.Builder</code></a>
-will not work.</p>
-
-<p>To continue enhancing your notifications for wearables using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
- ><code>WearableNotifications.Builder</code></a> and other APIs in the
- preview support library, see the following developer guides:</p>
-
- <dl>
- <dt><a href="/wear/notifications/remote-input.html">Receiving Voice Input
-from a Notification</a></dt>
- <dd>Add an action that receives voice input from the user and delivers the
-transcribed message to your app.</dd>
- <dt><a href="/wear/notifications/pages.html">Adding Pages to a Notification</a></dt>
- <dd>Add additional pages of information that are visible when the user
-swipes to the left.</dd>
- <dt><a href="/wear/notifications/stacks.html">Stacking Notifications</a></dt>
- <dd>Place all similar notifications from your app in a stack, allowing each to be
-viewed individually without adding multiple cards to the card stream.</dd>
- </dl>
-
-
-<div class="next-docs">
-
-<div class="col-12">
- <h2 class="norule">You might also want to read:</h2>
- <dl>
- <dt><a href="/training/notify-user/index.html">Notifying the User</a></dt>
- <dd>Learn more about how to create notifications.</dd>
- <dt><a href="/guide/components/intents-filters.html">Intents and Intent Filters</a></dt>
- <dd>Learn everything you need to know about the <code><a href="/reference/android/content/Intent.html">Intent</a></code>
-APIs, used by notificaton actions.</dd>
- </dl>
-</div>
-</div>
-
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
- <a href="/legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/creating.jd b/docs/html/wear/notifications/creating.jd
new file mode 100644
index 0000000..ce9e117
--- /dev/null
+++ b/docs/html/wear/notifications/creating.jd
@@ -0,0 +1,289 @@
+page.title=Creating Notifications for Android Wear
+
+@jd:body
+
+
+<p>When an Android device such as a phone or tablet is connected to an Android wearable,
+all notifications are shared between the devices by default. On the Android wearable, each
+notification appears as a new card in the <a href="{@docRoot}wear/design/user-interface.html#Stream"
+>context stream</a>.</p>
+
+<img src="{@docRoot}wear/images/notification_phone@2x.png" width="700" height="265" />
+
+
+<p>So without any effort, your app notifications are available to users on Android Wear.
+However, you can enhance the user experience in several ways. For instance,
+if users may respond to a notification by entering text, such as to reply to
+a message, you can add the ability for users to reply by voice directly from the
+wearable.</p>
+
+<p>To help you provide the best user experience
+for your notifications on Android Wear, this guide shows you how to
+build notifications using standard templates in
+the {@link android.support.v4.app.NotificationCompat.Builder} APIs, plus how to begin
+extending your notification's capabilities for the wearable user experience.</p>
+
+<p class="note"><strong>Note:</strong>
+Notifications using {@link android.widget.RemoteViews} are stripped of custom
+layouts and the system uses only the text and icons in the
+{@link android.app.Notification} object to
+display the notification in a card. However, custom card layouts will be supported by
+the official Android Wear SDK that is coming later.</p>
+</div>
+
+
+
+
+<h2 id="Import">Import the Necessary Classes</h2>
+
+<p>To begin development, you must first complete the instructions in the <a
+href="{@docRoot}wear/preview/start.html">Get Started with the Developer Preview</a> document.
+As mentioned in that document, your app must include
+both the <a href="http://developer.android.com/tools/support-library/features.html#v4">v4 support
+library</a> and the Developer Preview support library. So to get started,
+you should include the following imports in your project code:</p>
+
+<pre>
+import android.preview.support.wearable.notifications.*;
+import android.preview.support.v4.app.NotificationManagerCompat;
+import android.support.v4.app.NotificationCompat;
+</pre>
+
+<p class="caution"><strong>Caution:</strong>
+The APIs in the current Android Wear Developer Preview are intended for <b>development and testing purposes only</b>, not for production apps. Google may change this Developer Preview significantly prior to the official release of the Android Wear SDK. You may not publicly distribute or ship any application using this Developer Preview, as this Developer Preview will no longer be supported after the official SDK is released (which will cause applications based only on the Developer Preview to break).</p>
+
+
+
+<h2 id="NotificationBuilder">Create Notifications with the Notification Builder</h2>
+
+<p>The <a href="http://developer.android.com/tools/support-library/features.html#v4">v4
+support library</a> allows you to create notifications using the latest notification features
+such as action buttons and large icons, while remaining compatible with Android 1.6 (API level
+4) and higher.</p>
+
+
+<p>For example, here's some code that creates and issues a notification using the
+{@link android.support.v4.app.NotificationCompat} APIs combined with the new
+<a href="{@docRoot}reference/android/preview/support/v4/app/NotificationManagerCompat.html">
+<code>NotificationManagerCompat</code></a> API:</p>
+
+
+<pre>
+int notificationId = 001;
+// Build intent for notification content
+Intent viewIntent = new Intent(this, ViewEventActivity.class);
+viewIntent.putExtra(EXTRA_EVENT_ID, eventId);
+PendingIntent viewPendingIntent =
+ PendingIntent.getActivity(this, 0, viewIntent, 0);
+
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.ic_event)
+ .setContentTitle(eventTitle)
+ .setContentText(eventLocation)
+ .setContentIntent(viewPendingIntent);
+
+// Get an instance of the NotificationManager service
+NotificationManagerCompat notificationManager =
+ NotificationManagerCompat.from(this);
+
+// Build the notification and issues it with notification manager.
+notificationManager.notify(notificationId, notificationBuilder.build());
+</pre>
+
+<p>When this notification appears on a handheld device, the user can invoke the
+{@link android.app.PendingIntent}
+specified by the {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+setContentIntent()} method by touching the notification. When this
+notification appears on an Android wearable, the user can swipe the notification to the left to
+reveal the <strong>Open</strong> action, which invokes the intent on the handheld device.</p>
+
+
+
+
+
+
+<img src="{@docRoot}wear/images/circle_email_action.png" height="200" style="float:right;clear:right;margin:0 0 20px 60px" />
+
+<h2 id="ActionButtons">Add Action Buttons</h2>
+
+<p>In addition to the primary content action defined by
+{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+setContentIntent()}, you can add other actions by passing a {@link android.app.PendingIntent} to
+the {@link android.support.v4.app.NotificationCompat.Builder#addAction
+addAction()} method.</p>
+
+<p>For example, the following code shows the same type of notification from above, but adds an
+action to view the event location on a map.</p>
+
+<pre style="clear:right">
+// Build an intent for an action to view a map
+Intent mapIntent = new Intent(Intent.ACTION_VIEW);
+Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location));
+mapIntent.setData(geoUri);
+PendingIntent mapPendingIntent =
+ PendingIntent.getActivity(this, 0, mapIntent, 0);
+
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.ic_event)
+ .setContentTitle(eventTitle)
+ .setContentText(eventLocation)
+ .setContentIntent(viewPendingIntent)
+ <b>.addAction(R.drawable.ic_map,
+ getString(R.string.map), mapPendingIntent);</b>
+</pre>
+
+<p>On a handheld device, the action appears as an
+additional button attached to the notification. On an Android wearable, the action appears as
+a large button when the user swipes the notification to the left. When the user taps the action,
+the associated {@link android.content.Intent} is invoked on the handheld device.</p>
+
+<p class="note"><strong>Tip:</strong> If your notifications includes a "Reply" action
+ (such as for a messaging app), you can enhance the behavior by enabling
+ voice input replies directly from the Android wearable. For more information, read
+ <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from a Notification</a>.
+</p>
+
+<p>For details about designing action buttons (including the icon specifications), see the
+<a href="{@docRoot}wear/design/index.html#NotifictionActions">Design Principles of Android
+Wear</a>.</p>
+
+
+<h2 id="BigView">Add a Big View</h2>
+
+<img src="{@docRoot}wear/images/06_images.png" height="200" style="float:right;margin:0 0 20px 40px" />
+
+<p>You can insert extended text content
+to your notification by adding one of the "big view" styles to your notification. On a
+handheld device, users can see the big view content by expanding the notification,
+while on Android Wear, the big view content is visible by default.</p>
+
+<p>To add the extended content to your notification, call {@link
+android.support.v4.app.NotificationCompat.Builder#setStyle setStyle()} on the {@link
+android.support.v4.app.NotificationCompat.Builder} object, passing it an instance of either
+{@link android.support.v4.app.NotificationCompat.BigTextStyle BigTextStyle} or
+{@link android.support.v4.app.NotificationCompat.InboxStyle InboxStyle}.</p>
+
+<p>For example, the following code adds an instance of
+{@link android.support.v4.app.NotificationCompat.BigTextStyle} to the event notification,
+in order to include the complete event description (which includes more text than can fit
+into the space provided for {@link android.support.v4.app.NotificationCompat.Builder#setContentText
+setContentText()}).</p>
+
+
+<pre style="clear:right">
+// Specify the 'big view' content to display the long
+// event description that may not fit the normal content text.
+BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
+bigStyle.bigText(eventDescription);
+
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.ic_event)
+ .setLargeIcon(BitmapFractory.decodeResource(
+ getResources(), R.drawable.notif_background))
+ .setContentTitle(eventTitle)
+ .setContentText(eventLocation)
+ .setContentIntent(viewPendingIntent)
+ .addAction(R.drawable.ic_map,
+ getString(R.string.map), mapPendingIntent)
+ <b>.setStyle(bigStyle);</b>
+</pre>
+
+<p>Notice that you can add a large background image to any notification using the
+{@link android.support.v4.app.NotificationCompat.Builder#setLargeIcon setLargeIcon()}
+method. For more information about designing notifications with large images, see the
+<a href="{@docRoot}wear/design/index.html#Images">Design Principles of Android
+Wear</a>.</p>
+
+
+
+<h2 id="NewFeatures">Add New Features for Wearables</h2>
+
+<p>The Android Wear preview support library provides new APIs that
+ allow you to enhance the user experience for notifications on a wearable device. For example,
+ you can add additional pages of content that users can view by swiping to the left, or add the ability
+for users to deliver your app a text response using voice input.</p>
+
+<p>To use these new APIs, pass your instance of
+{@link android.support.v4.app.NotificationCompat.Builder} to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#WearableNotifications.Builder(android.content.Context)"> <code>WearableNotifications.Builder()</code></a> constructor. You can then add new
+features to your notification using the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
+ ><code>WearableNotifications.Builder</code></a> methods. For example:</p>
+
+<pre>
+// Create a NotificationCompat.Builder for standard notification features
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(mContext)
+ .setContentTitle("New mail from " + sender.toString())
+ .setContentText(subject)
+ .setSmallIcon(R.drawable.new_mail);
+
+// Create a WearablesNotification.Builder to add special functionality for wearables
+Notification notification =
+ new WearableNotifications.Builder(notificationBuilder)
+ .setHintHideIcon(true)
+ .build();
+</pre>
+
+<p>The <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setBigActionIcon(int)">
+ <code>setHintHideIcon()</code></a> method removes your app icon from the notification card.
+ This method is just one example of new notification features available from the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
+ ><code>WearableNotifications.Builder</code></a> class.</p>
+
+<p>When you want to deliver your notifications, be certain to always use the
+ <a href="{@docRoot}reference/android/preview/support/v4/app/NotificationManagerCompat.html">
+ <code>NotificationManagerCompat</code></a> API:</p>
+
+<pre>
+// Get an instance of the NotificationManager service
+NotificationManagerCompat notificationManager =
+ NotificationManagerCompat.from(this);
+
+// Build the notification and issues it with notification manager.
+notificationManager.notify(notificationId, notification);
+</pre>
+
+<p>If you instead use the framework's {@link android.app.NotificationManager}, some
+features from <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"><code>WearableNotifications.Builder</code></a>
+will not work.</p>
+
+<p>To continue enhancing your notifications for wearables using
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
+ ><code>WearableNotifications.Builder</code></a> and other APIs in the
+ preview support library, see the following developer guides:</p>
+
+ <dl>
+ <dt><a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input
+from a Notification</a></dt>
+ <dd>Add an action that receives voice input from the user and delivers the
+transcribed message to your app.</dd>
+ <dt><a href="{@docRoot}wear/notifications/pages.html">Adding Pages to a Notification</a></dt>
+ <dd>Add additional pages of information that are visible when the user
+swipes to the left.</dd>
+ <dt><a href="{@docRoot}wear/notifications/stacks.html">Stacking Notifications</a></dt>
+ <dd>Place all similar notifications from your app in a stack, allowing each to be
+viewed individually without adding multiple cards to the card stream.</dd>
+ </dl>
+
+
+<div class="next-docs">
+
+<div class="col-12">
+ <h2 class="norule">You might also want to read:</h2>
+ <dl>
+ <dt><a href="{@docRoot}training/notify-user/index.html">Notifying the User</a></dt>
+ <dd>Learn more about how to create notifications.</dd>
+ <dt><a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a></dt>
+ <dd>Learn everything you need to know about the {@link android.content.Intent}
+APIs, used by notificaton actions.</dd>
+ </dl>
+</div>
+</div>
+
+
+</body>
+</html>
diff --git a/docs/html/wear/notifications/pages.html b/docs/html/wear/notifications/pages.html
deleted file mode 100644
index ce568eb..0000000
--- a/docs/html/wear/notifications/pages.html
+++ /dev/null
@@ -1,500 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Adding Pages to a Notification | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Adding Pages to a Notification</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <img src="/wear/images/09_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
-<img src="/wear/images/08_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>When you'd like to provide more information without requiring users
-to open your app on their handheld device, you can
-add one or more pages to the notification on Android Wear. The additional pages
-appear immediately to the right of the main notification card.
-For information about when to use and how to design
-multiple pages, see the
-<a href="/wear/design/index.html#NotificationPages">Design Principles of Android
-Wear</a>.</p>
-
-
-<p>When creating a notification with multiple pages, start by creating the main notification
-(the first page) the way you'd like the notification to appear on a phone
-or tablet. Then, add pages one at a time with the
-<a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addPage(android.app.Notification)">
-<code>addPage()</code></a> method, or add multiple pages in a <code><a href="/reference/java/util/Collection.html">Collection</a></code> with the
-<a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addPages(java.util.Collection<android.app.Notification>)">
-<code>addPages()</code></a> method.</p>
-
-
-<p>For example, here's some code that adds a second page to a notification:</p>
-
-<pre>
-// Create builder for the main notification
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.new_message)
- .setContentTitle("Page 1")
- .setContentText("Short message")
- .setContentIntent(viewPendingIntent);
-
-// Create a big text style for the second page
-BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
-secondPageStyle.setBigContentTitle("Page 2")
- .bigText("A lot of text...");
-
-// Create second page notification
-Notification secondPageNotification =
- new NotificationCompat.Builder(this)
- .setStyle(secondPageStyle)
- .build();
-
-// Create main notification and add the second page
-Notification twoPageNotification =
- new WearableNotifications.Builder(notificationBuilder)
- .addPage(secondPageNotification)
- .build();
-</pre>
-
-
-
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
- <a href="/legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/pages.jd b/docs/html/wear/notifications/pages.jd
new file mode 100644
index 0000000..558f7b8
--- /dev/null
+++ b/docs/html/wear/notifications/pages.jd
@@ -0,0 +1,61 @@
+page.title=Adding Pages to a Notification
+
+@jd:body
+
+
+<img src="{@docRoot}wear/images/09_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
+<img src="{@docRoot}wear/images/08_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
+
+<p>When you'd like to provide more information without requiring users
+to open your app on their handheld device, you can
+add one or more pages to the notification on Android Wear. The additional pages
+appear immediately to the right of the main notification card.
+For information about when to use and how to design
+multiple pages, see the
+<a href="{@docRoot}wear/design/index.html#NotificationPages">Design Principles of Android
+Wear</a>.</p>
+
+
+<p>When creating a notification with multiple pages, start by creating the main notification
+(the first page) the way you'd like the notification to appear on a phone
+or tablet. Then, add pages one at a time with the
+<a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addPage(android.app.Notification)">
+<code>addPage()</code></a> method, or add multiple pages in a {@link java.util.Collection} with the
+<a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addPages(java.util.Collection<android.app.Notification>)">
+<code>addPages()</code></a> method.</p>
+
+
+<p>For example, here's some code that adds a second page to a notification:</p>
+
+<pre>
+// Create builder for the main notification
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.new_message)
+ .setContentTitle("Page 1")
+ .setContentText("Short message")
+ .setContentIntent(viewPendingIntent);
+
+// Create a big text style for the second page
+BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
+secondPageStyle.setBigContentTitle("Page 2")
+ .bigText("A lot of text...");
+
+// Create second page notification
+Notification secondPageNotification =
+ new NotificationCompat.Builder(this)
+ .setStyle(secondPageStyle)
+ .build();
+
+// Create main notification and add the second page
+Notification twoPageNotification =
+ new WearableNotifications.Builder(notificationBuilder)
+ .addPage(secondPageNotification)
+ .build();
+</pre>
+
+
+
+
+</body>
+</html>
diff --git a/docs/html/wear/notifications/remote-input.html b/docs/html/wear/notifications/remote-input.html
deleted file mode 100644
index 3d869b5..0000000
--- a/docs/html/wear/notifications/remote-input.html
+++ /dev/null
@@ -1,652 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Receiving Voice Input from a Notification | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Receiving Voice Input from a Notification</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <img src="/wear/images/13_voicereply.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-
-<img src="/wear/images/03_actions.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-
-<p>If your notification includes an action to respond with text,
- such as to reply to an email, it should normally launch an activity
- on the handheld device. However, when your notification appears on an Android wearable, you can
- allow users to dictate a reply with voice input. You can also provide pre-defined text
- messages for the user to select.</p>
-
-<p>When the user replies with voice or selects one of the available
-messages, the system sends the message to your app on the connected handheld device.
-The message is attached as an extra in the <code><a href="/reference/android/content/Intent.html">Intent</a></code> you specified
-to be used for the notification action.</p>
-
-<p class="note"><strong>Note:</strong> When developing with the Android emulator,
-you must type text replies into the voice input field, so be sure you have enabled
-<strong>Hardware keyboard present</strong> in the AVD settings.</p>
-
-
-<h2 id="RemoteInput">Define the Remote Input</h2>
-
-<p>To create an action that supports voice input, first create an instance of
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">
-<code>RemoteInput</code></a> using the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> APIs.
- The
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor takes a string that the system
- will use as a key for the <code><a href="/reference/android/content/Intent.html">Intent</a></code> extra that carries the reply message
- to your app on the handheld.</p>
-
-<p>For example, here's how to create a new
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">
-<code>RemoteInput</code></a> object that provides a custom
- label for the voice input prompt:</p>
-
-<pre class="prettyprint">
-// Key for the string that's delivered in the action's intent
-private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
-
-String replyLabel = getResources().getString(R.string.reply_label);
-
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
- .setLabel(replyLabel)
- .build();
-</pre>
-
-
-<h3>Add Pre-defined Text Responses</h3>
-
-<img src="/wear/images/12_voicereply.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>In addition to allowing voice input, you can
- provide up to five text responses that the user can select for quick replies. Call
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html#setChoices(java.lang.String[])"><code>setChoices()</code></a> and pass it a string array.</p>
-
-<p>For example, you may define some responses in a resource array:</p>
-
-<p class="code-caption">res/values/strings.xml</code>
-<pre class="prettyprint">
-&lt;?xml version="1.0" encoding="utf-8"?>
-&lt;resources>
- &lt;string-array name="reply_choices">
- &lt;item>Yes&lt;/item>
- &lt;item>No&lt;/item>
- &lt;item>Maybe&lt;/item>
- &lt;/string-array>
-&lt;/resources>
-</pre>
-
-<p>Then, inflate the string array and add it to the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a>:</p>
-
-<pre>
-String replyLabel = getResources().getString(R.string.reply_label);
-String[] replyChoices = getResources().getStringArray(R.array.reply_choices);
-
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
- .setLabel(replyLabel)
- .setChoices(replyChoices)
- .build();
-</pre>
-
-
-
-
-<h2 id="PrimaryAction">Receive Voice Input for the Primary Action</h2>
-
-<p>If "Reply" is your notification's primary action (defined by the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)">setContentIntent()</a></code>
-method), then you should attach the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the main action using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addRemoteInputForContentIntent(android.preview.support.wearable.notifications.RemoteInput)">
-<code>addRemoteInputForContentIntent()</code></a>. For example:</p>
-
-<pre>
-// Create intent for reply action
-Intent replyIntent = new Intent(this, ReplyActivity.class);
-PendingIntent replyPendingIntent =
- PendingIntent.getActivity(this, 0, replyIntent, 0);
-
-// Build the notification
-NotificationCompat.Builder replyNotificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.ic_new_message)
- .setContentTitle("Message from Travis")
- .setContentText("I love key lime pie!")
- .setContentIntent(replyPendingIntent);
-
-// Create the remote input
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
- .setLabel(replyLabel)
- .build();
-
-// Create wearable notification and add remote input
-Notification replyNotification =
- new WearableNotifications.Builder(replyNotificationBuilder)
- .addRemoteInputForContentIntent(remoteInput)
- .build();
-</pre>
-
-
-<p>By using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addRemoteInputForContentIntent(android.preview.support.wearable.notifications.RemoteInput)">
-<code>addRemoteInputForContentIntent()</code></a> to add the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> object to the notification's primary action,
-the button that normally appears as an "Open" action becomes the "Reply" action
-and starts the voice input UI when users select it on Android Wear.</p>
-
-
-
-<h2 id="NewAction">Receive Voice Input for a Secondary Action</h2>
-
-<p>If the "Reply" action is not your notification's primary action and you want to enable
-voice input for a secondary action, add the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to a new action button defined by an
- <a href="/reference/android/preview/support/wearable/notifications/Action.html">
-<code>Action</code></a> object.</p>
-
-<p>You should instantiate the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
-<code>Action</code></a> with the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html"><code>Action.Builder()</code></a>
-constructor, which takes an icon and text label for the action button, plus the
-<code><a href="/reference/android/app/PendingIntent.html">PendingIntent</a></code>
-the system should use to invoke your app when the user selects the action. For example:</p>
-
-<pre>
-// Create the pending intent to fire when the user selects the action
-Intent replyIntent = new Intent(this, ReplyActivity.class);
-PendingIntent pendingReplyIntent =
- PendingIntent.getActivity(this, 0, replyIntent, 0);
-
-// Create the remote input
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
- .setLabel(replyLabel)
- .build();
-
-// Create the notification action
-Action replyAction = new Action.Builder(R.drawable.ic_message,
- "Reply", pendingIntent)
- .addRemoteInput(remoteInput)
- .build();
-</pre>
-
-
-<p>After you add the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
-<code>Action</code></a>, add the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
-<code>Action</code></a> to the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"><code>WearableNotifications.Builder</code></a> using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addAction(Action)"><code>addAction()</code></a>.
-For example:</p>
-
-<pre>
-// Create basic notification builder
-NotificationCompat.Builder replyNotificationBuilder =
- new NotificationCompat.Builder(this)
- .setContentTitle("New message");
-
-// Create the notification action and add remote input
-Action replyAction = new Action.Builder(R.drawable.ic_message,
- "Reply", pendingIntent)
- .addRemoteInput(remoteInput)
- .build();
-
-// Create wearable notification and add action
-Notification replyNotification =
- new WearableNotifications.Builder(replyNotificationBuilder)
- .addAction(replyAction)
- .build();
-</pre>
-
-<p>Now, when the user selects "Reply" from an Android wearable, the system prompts the user
- for voice input (and shows the list of pre-defined replies, if provided).
- Once the user completes a response, the system invokes
- the <code><a href="/reference/android/content/Intent.html">Intent</a></code> attached to the action and adds the
-<code>EXTRA_VOICE_REPLY</code> extra (the string
- you passed to the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor)
- with the user's message as the string value.</p>
-
-
-
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
- <a href="/legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/remote-input.jd b/docs/html/wear/notifications/remote-input.jd
new file mode 100644
index 0000000..1668363
--- /dev/null
+++ b/docs/html/wear/notifications/remote-input.jd
@@ -0,0 +1,213 @@
+page.title=Receiving Voice Input from a Notification
+
+@jd:body
+
+<img src="{@docRoot}wear/images/13_voicereply.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
+
+<img src="{@docRoot}wear/images/03_actions.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
+
+<p>If your notification includes an action to respond with text,
+ such as to reply to an email, it should normally launch an activity
+ on the handheld device. However, when your notification appears on an Android wearable, you can
+ allow users to dictate a reply with voice input. You can also provide pre-defined text
+ messages for the user to select.</p>
+
+<p>When the user replies with voice or selects one of the available
+messages, the system sends the message to your app on the connected handheld device.
+The message is attached as an extra in the {@link android.content.Intent} you specified
+to be used for the notification action.</p>
+
+<p class="note"><strong>Note:</strong> When developing with the Android emulator,
+you must type text replies into the voice input field, so be sure you have enabled
+<strong>Hardware keyboard present</strong> in the AVD settings.</p>
+
+
+<h2 id="RemoteInput">Define the Remote Input</h2>
+
+<p>To create an action that supports voice input, first create an instance of
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html">
+<code>RemoteInput</code></a> using the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> APIs.
+ The
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor takes a string that the system
+ will use as a key for the {@link android.content.Intent} extra that carries the reply message
+ to your app on the handheld.</p>
+
+<p>For example, here's how to create a new
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html">
+<code>RemoteInput</code></a> object that provides a custom
+ label for the voice input prompt:</p>
+
+<pre class="prettyprint">
+// Key for the string that's delivered in the action's intent
+private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
+
+String replyLabel = getResources().getString(R.string.reply_label);
+
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+ .setLabel(replyLabel)
+ .build();
+</pre>
+
+
+<h3>Add Pre-defined Text Responses</h3>
+
+<img src="{@docRoot}wear/images/12_voicereply.png" height="200" style="float:right;margin:0 0 20px 40px" />
+
+<p>In addition to allowing voice input, you can
+ provide up to five text responses that the user can select for quick replies. Call
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html#setChoices(java.lang.String[])"><code>setChoices()</code></a> and pass it a string array.</p>
+
+<p>For example, you may define some responses in a resource array:</p>
+
+<p class="code-caption">res/values/strings.xml</code>
+<pre class="prettyprint">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+ &lt;string-array name="reply_choices">
+ &lt;item>Yes&lt;/item>
+ &lt;item>No&lt;/item>
+ &lt;item>Maybe&lt;/item>
+ &lt;/string-array>
+&lt;/resources>
+</pre>
+
+<p>Then, inflate the string array and add it to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a>:</p>
+
+<pre>
+String replyLabel = getResources().getString(R.string.reply_label);
+String[] replyChoices = getResources().getStringArray(R.array.reply_choices);
+
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+ .setLabel(replyLabel)
+ .setChoices(replyChoices)
+ .build();
+</pre>
+
+
+
+
+<h2 id="PrimaryAction">Receive Voice Input for the Primary Action</h2>
+
+<p>If "Reply" is your notification's primary action (defined by the {@link
+android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}
+method), then you should attach the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the main action using
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addRemoteInputForContentIntent(android.preview.support.wearable.notifications.RemoteInput)">
+<code>addRemoteInputForContentIntent()</code></a>. For example:</p>
+
+<pre>
+// Create intent for reply action
+Intent replyIntent = new Intent(this, ReplyActivity.class);
+PendingIntent replyPendingIntent =
+ PendingIntent.getActivity(this, 0, replyIntent, 0);
+
+// Build the notification
+NotificationCompat.Builder replyNotificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.ic_new_message)
+ .setContentTitle("Message from Travis")
+ .setContentText("I love key lime pie!")
+ .setContentIntent(replyPendingIntent);
+
+// Create the remote input
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+ .setLabel(replyLabel)
+ .build();
+
+// Create wearable notification and add remote input
+Notification replyNotification =
+ new WearableNotifications.Builder(replyNotificationBuilder)
+ .addRemoteInputForContentIntent(remoteInput)
+ .build();
+</pre>
+
+
+<p>By using
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addRemoteInputForContentIntent(android.preview.support.wearable.notifications.RemoteInput)">
+<code>addRemoteInputForContentIntent()</code></a> to add the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> object to the notification's primary action,
+the button that normally appears as an "Open" action becomes the "Reply" action
+and starts the voice input UI when users select it on Android Wear.</p>
+
+
+
+<h2 id="NewAction">Receive Voice Input for a Secondary Action</h2>
+
+<p>If the "Reply" action is not your notification's primary action and you want to enable
+voice input for a secondary action, add the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to a new action button defined by an
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
+<code>Action</code></a> object.</p>
+
+<p>You should instantiate the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
+<code>Action</code></a> with the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html"><code>Action.Builder()</code></a>
+constructor, which takes an icon and text label for the action button, plus the
+{@link android.app.PendingIntent}
+the system should use to invoke your app when the user selects the action. For example:</p>
+
+<pre>
+// Create the pending intent to fire when the user selects the action
+Intent replyIntent = new Intent(this, ReplyActivity.class);
+PendingIntent pendingReplyIntent =
+ PendingIntent.getActivity(this, 0, replyIntent, 0);
+
+// Create the remote input
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+ .setLabel(replyLabel)
+ .build();
+
+// Create the notification action
+Action replyAction = new Action.Builder(R.drawable.ic_message,
+ "Reply", pendingIntent)
+ .addRemoteInput(remoteInput)
+ .build();
+</pre>
+
+
+<p>After you add the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
+<code>Action</code></a>, add the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
+<code>Action</code></a> to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"><code>WearableNotifications.Builder</code></a> using
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addAction(Action)"><code>addAction()</code></a>.
+For example:</p>
+
+<pre>
+// Create basic notification builder
+NotificationCompat.Builder replyNotificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setContentTitle("New message");
+
+// Create the notification action and add remote input
+Action replyAction = new Action.Builder(R.drawable.ic_message,
+ "Reply", pendingIntent)
+ .addRemoteInput(remoteInput)
+ .build();
+
+// Create wearable notification and add action
+Notification replyNotification =
+ new WearableNotifications.Builder(replyNotificationBuilder)
+ .addAction(replyAction)
+ .build();
+</pre>
+
+<p>Now, when the user selects "Reply" from an Android wearable, the system prompts the user
+ for voice input (and shows the list of pre-defined replies, if provided).
+ Once the user completes a response, the system invokes
+ the {@link android.content.Intent} attached to the action and adds the
+<code>EXTRA_VOICE_REPLY</code> extra (the string
+ you passed to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor)
+ with the user's message as the string value.</p>
+
+
+
+
+</body>
+</html>
diff --git a/docs/html/wear/notifications/stacks.html b/docs/html/wear/notifications/stacks.html
deleted file mode 100644
index e4f74a0..0000000
--- a/docs/html/wear/notifications/stacks.html
+++ /dev/null
@@ -1,512 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Stacking Notifications | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Stacking Notifications</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <img src="/wear/images/11_bundles_B.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-<img src="/wear/images/11_bundles_A.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-
-<p>When creating notifications for a handheld device, you should always aggregate similar
-notifications into a single summary notification. For example, if your app creates notifications
-for received messages, you should not show more than one notification
-on a handheld device&mdash;when more than one is message is received, use a single notification
-to provide a summary such as "2 new messages."</p>
-
-<p>However, a summary notification is less useful on an Android wearable because users
-are not able to read details from each message on the wearable (they must open your app on the
-handheld to view more information). So for the wearable device, you should
-group all the notifications together in a stack. The stack of notifications appears as a single
-card, which users can expand to view the details from each notification separately. The new
-<a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
-<code>setGroup()</code></a> method makes this possible while allowing you to still provide
-only one summary notification on the handheld device.</p>
-
-<p>For details about designing notification stacks, see the
-<a href="/wear/design/index.html#NotificationStacks">Design Principles of Android
-Wear</a>.</p>
-
-
-<h2 id="AddGroup">Add Each Notification to a Group</h2>
-
-<p>To create a stack, call <a
-href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
-<code>setGroup()</code></a> for each notification you want in the stack, passing the same
-group key. For example:</p>
-
-<pre style="clear:right">
-final static String GROUP_KEY_EMAILS = "group_key_emails";
-
-NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext)
- .setContentTitle("New mail from " + sender)
- .setContentText(subject)
- .setSmallIcon(R.drawable.new_mail);
-
-Notification notif = new WearableNotifications.Builder(builder)
- .setGroup(GROUP_KEY_EMAILS)
- .build();
-</pre>
-
-<p>By default, notifications appear in the order in which you added them, with the most recent
- notification visible at the top. You can define a specific position in the group
- by passing an order position as the second parameter for <a
-href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
-<code>setGroup()</code></a>.</p>
-
-
-<h2 id="AddSummary">Add a Summary Notification</h2>
-
-<p>It's important that you still provide a summary notification that appears on handheld devices.
-So in addition to adding each unique notification to the same stack group, also add a summary
-notification, but set its order position to be <a
-href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html#GROUP_ORDER_SUMMARY"><code>GROUP_ORDER_SUMMARY</code></a>.</p>
-
-<pre>
-Notification summaryNotification = new WearableNotifications.Builder(builder)
- .setGroup(GROUP_KEY_EMAILS, WearableNotifications.GROUP_ORDER_SUMMARY)
- .build();
-</pre>
-
-<p>This notification will not appear in your stack of notifications on the wearable, but
-appears as the only notification on the handheld device.
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
- <a href="/legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/stacks.jd b/docs/html/wear/notifications/stacks.jd
new file mode 100644
index 0000000..7f955f6
--- /dev/null
+++ b/docs/html/wear/notifications/stacks.jd
@@ -0,0 +1,72 @@
+page.title=Stacking Notifications
+
+@jd:body
+
+<img src="{@docRoot}wear/images/11_bundles_B.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
+<img src="{@docRoot}wear/images/11_bundles_A.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
+
+<p>When creating notifications for a handheld device, you should always aggregate similar
+notifications into a single summary notification. For example, if your app creates notifications
+for received messages, you should not show more than one notification
+on a handheld device&mdash;when more than one is message is received, use a single notification
+to provide a summary such as "2 new messages."</p>
+
+<p>However, a summary notification is less useful on an Android wearable because users
+are not able to read details from each message on the wearable (they must open your app on the
+handheld to view more information). So for the wearable device, you should
+group all the notifications together in a stack. The stack of notifications appears as a single
+card, which users can expand to view the details from each notification separately. The new
+<a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
+<code>setGroup()</code></a> method makes this possible while allowing you to still provide
+only one summary notification on the handheld device.</p>
+
+<p>For details about designing notification stacks, see the
+<a href="{@docRoot}wear/design/index.html#NotificationStacks">Design Principles of Android
+Wear</a>.</p>
+
+
+<h2 id="AddGroup">Add Each Notification to a Group</h2>
+
+<p>To create a stack, call <a
+href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
+<code>setGroup()</code></a> for each notification you want in the stack, passing the same
+group key. For example:</p>
+
+<pre style="clear:right">
+final static String GROUP_KEY_EMAILS = "group_key_emails";
+
+NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext)
+ .setContentTitle("New mail from " + sender)
+ .setContentText(subject)
+ .setSmallIcon(R.drawable.new_mail);
+
+Notification notif = new WearableNotifications.Builder(builder)
+ .setGroup(GROUP_KEY_EMAILS)
+ .build();
+</pre>
+
+<p>By default, notifications appear in the order in which you added them, with the most recent
+ notification visible at the top. You can define a specific position in the group
+ by passing an order position as the second parameter for <a
+href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
+<code>setGroup()</code></a>.</p>
+
+
+<h2 id="AddSummary">Add a Summary Notification</h2>
+
+<p>It's important that you still provide a summary notification that appears on handheld devices.
+So in addition to adding each unique notification to the same stack group, also add a summary
+notification, but set its order position to be <a
+href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.html#GROUP_ORDER_SUMMARY"><code>GROUP_ORDER_SUMMARY</code></a>.</p>
+
+<pre>
+Notification summaryNotification = new WearableNotifications.Builder(builder)
+ .setGroup(GROUP_KEY_EMAILS, WearableNotifications.GROUP_ORDER_SUMMARY)
+ .build();
+</pre>
+
+<p>This notification will not appear in your stack of notifications on the wearable, but
+appears as the only notification on the handheld device.
+
+</body>
+</html>
diff --git a/docs/html/wear/preview/signup.html b/docs/html/wear/preview/signup.jd
index ca50179..8e8ec9a 100644
--- a/docs/html/wear/preview/signup.html
+++ b/docs/html/wear/preview/signup.jd
@@ -1,379 +1,8 @@
-<!DOCTYPE html>
+page.title=Sign Up for the Developer Preview
+@jd:body
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Sign Up for the Developer Preview | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Sign Up for the Developer Preview</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <p>To get started with the Android Wear Developer Preview, you must agree to the
+<p>To get started with the Android Wear Developer Preview, you must agree to the
following terms and conditions and provide the email address for your Google account.
After signing up, you’ll have access to:</p>
<ul>
@@ -538,72 +167,3 @@ This is the Android Wear Developer Preview License Agreement.
</body>
</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
- <a href="/legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/preview/start.html b/docs/html/wear/preview/start.html
deleted file mode 100644
index b1861f5..0000000
--- a/docs/html/wear/preview/start.html
+++ /dev/null
@@ -1,693 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Get Started with the Developer Preview | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display">&nbsp;</div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Get Started with the Developer Preview</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <div class="cols">
-
- <div class="col-5">
-<p>The Android Wear Developer Preview includes tools and APIs that allow you to
-enhance your app notifications
-to provide an optimized user experience on Android wearables.</p>
-
-<p>With the Android Wear Developer Preview, you can:</p>
-
-<ul>
- <li>Run the Android Wear platform in the Android emulator.</li>
- <li>Connect your Android device to the emulator and view notifications from the
-device as cards on Android Wear.</li>
- <li>Try new APIs in the preview support library that enhance your app's notifications
-with features such as voice replies and notification pages.</li>
-</ul>
-
-<p>To get access to the Developer Preview tools,
-click the sign up button on the right, then follow the setup instructions below.</p>
- </div>
-
- <div class="col-7">
-<img src="/wear/images/laptop-bridge.png" width="400" height="222" alt="" />
-
-<a href="/wear/preview/signup.html" class="button" style="
- width: 370px;
- margin: 10px 0 20px;
- font-weight: bold;
- font-size: 16px;
-">Sign Up for the Developer Preview</a>
-
-<p>Signing up provides you access to:</p>
-<ul>
-<li>New notification APIs in the preview support library.</li>
-<li>Sample apps using the new notification APIs.</li>
-<li>The <em>Android Wear Preview</em> app for your mobile device, which connects
-your device to the Android Wear emulator.</li>
-</ul>
-
- </div>
-</div>
-
-
-<p class="caution"><strong>Caution:</strong>
-The current Android Wear Developer Preview is intended for <b>development and testing purposes only</b>, not for production apps. Google may change this Developer Preview significantly prior to the official release of the Android Wear SDK. You may not publicly distribute or ship any application using this Developer Preview, as this Developer Preview will no longer be supported after the official SDK is released (which will cause applications based only on the Developer Preview to break).</p>
-
-
-
-
-<h2 id="Prereq">Prerequisites</h2>
-
-<p>Before you begin the setup, you must:</p>
-
-<ol>
- <li><a href="/sdk/index.html"><b>Install the Android SDK</b></a>.
- <p>The Android SDK includes all the developer tools required to build
-apps for Android (optional IDEs are also available for download).</p></li>
- <li><a href="/wear/preview/signup.html"><b>Sign up for the Android Wear Developer Preview</b></a>.
- <p>You must sign up with a Gmail or other Google account in order to download the
-preview support library and receive access to the
-<em>Android Wear Preview</em> beta app on Google Play Store.</p></li>
-</ol>
-
-<p class="note"><strong>Note:</strong>
-If you're using the ADT plugin for Eclipse, you must update to version 22.6.1 or higher.
-If you're using Android Studio, you must update to version 0.5.1 or higher</p>
-
-
-
-<h2 id="Install">1. Install the Android Wear System Image</h2>
-
-
-<ol>
- <li>Launch <a href="/tools/help/sdk-manager.html"
- >Android SDK Manager</a>.
- <ul>
- <li>From Eclipse, select <b>Window > Android SDK Manager</b>.</li>
- <li>From Android Studio, select <b>Tools > Android > SDK Manager</b>.</li>
- </ul>
- </li>
- <li>Below Tools, verify that you have Android SDK Tools revision 22.6 or higher.
- <p>If your version of Android SDK Tools is lower than 22.6, you must update:</p>
- <ol>
- <li>Select <strong>Android SDK Tools</strong>.</li>
- <li>Click <strong>Install package</strong>.</li>
- <li>Accept the license and click <strong>Install</strong>.</li>
- <li>When the installation completes, restart Android SDK Manager.</li>
- </ol>
- </li>
-
- <li>Below Android 4.4.2, select <strong>Android Wear ARM EABI v7a System Image</strong>.
-<p class="note"><strong>Note:</strong> Android Wear is designed to support multiple processor architectures.
-</p></li>
- <li>Below Extras, ensure that you have the latest version of the
-<a href="/tools/support-library/index.html">Android Support Library</a>.
- If an update is available, select <strong>Android Support Library</strong>. If you're using Android Studio, also select <strong>Android Support Repository</strong>.</li>
- <li>Click <strong>Install packages</strong>.</li>
- <li>Accept the license and click <strong>Install</strong>.</li>
-</ol>
-
-
-
-<h2 id="SetupEmulator">2. Set Up the Android Wear Emulator</h2>
-
-<ol>
-<li>Launch the <a href="/tools/help/avd-manager.html"
- >Android Virtual Device Manager</a>.
-<ul>
-<li>From Eclipse, select <b>Window > Android Virtual Device Manager</b>.</li>
-<li>From Android Studio, select <b>Tools > Android > AVD Manager</b>.</li>
-</ul>
-</li>
-<li>Click <strong>New</strong>.</li>
-<li>For the AVD Name, enter "AndroidWearSquare" or "AndroidWearRound", depending on whether
-you want to create an emulator with a square or round display.</li>
-<li>For the Device, select <strong>Android Wear Square</strong> or
- <strong>Android Wear Round</strong>.</li>
-<li>For the Target, select <strong>Android 4.4.2 - API Level 19</strong> (or higher).</li>
-<li>For the CPU/ABI, select <strong>Android Wear ARM (armeabi-v7a)</strong>.
-<p class="note"><strong>Note:</strong> Android Wear is designed to support multiple processor architectures.
-</p></li>
-<li>For the Skin, select <strong>AndroidWearSquare</strong> or
-<strong>AndroidWearRound</strong>.</li>
-<li>Leave all other options set to their defaults and click <strong>OK</strong>.
- <p>Although real Android wearables do not provide a keyboard as an input method,
- you should keep <strong>Hardware keyboard present</strong> selected so you can
- provide text input on screens where users will instead provide voice input.</p>
-</li>
-<!--
-<li>Click <strong>Device Definitions</strong>.</li>
-<li>Select <strong>Android WearSquare</strong> then click <strong>Create AVD</strong>.</li>
-<li>Click <strong>OK</strong>.</li>
--->
-<li>In the list of AVDs, select the one you just created and click
- <strong>Start</strong>. In the following window, click <strong>Launch</strong>.</li>
-</ol>
-
-<p>The Android Wear emulator now starts. To begin testing your app's notifications,
-you must now pair the emulator to your development device
-that has the <em>Android Wear Preview</em> app installed.</p>
-
-<p class="note"><strong>Tip:</strong> To improve the emulator startup time, edit your AVD
-and enable <strong>Snapshot</strong> under Emulator Options. When you start the emulator,
-select <strong>Save to snapshot</strong> then click <strong>Launch</strong>. Once the emulator
-is running, close it to save a snapshot of the system.
-Start the AVD again, but select <strong>Launch from snapshot</strong> and
-deselect <strong>Save to snapshot</strong>.</p>
-
-<p class="caution"><strong>Caution:</strong> Do not install apps on the Android Wear emulator.
-The system does not support traditional Android apps and the result of running such apps is
-unpredictable.</p>
-
-
-
-<h2 id="SetupApp">3. Set Up the Android Wear Preview App</h2>
-
-<p>To view your app's notifications on the Android Wear emulator, you must have the
-<em>Android Wear Preview</em> app installed on your Android device (a phone or tablet).</p>
-
-<p>To receive the Android Wear Preview app, you must <a
-href="/wear/preview/signup.html">sign up for the Developer Preview</a> using the same
-Gmail or Google account you use with Google Play Store.</p>
-</p>
-
-<p class="note"><strong>Note:</strong> The <em>Android Wear Preview</em> app is compatible with
- Android 4.3 and higher and is not available for the Android emulator.</p>
-
-<p>After you've signed up for the Developer Preview,
- you'll receive a confirmation email that includes a link to opt-in to the
- <em>Android Wear Preview</em> app beta program. Once you opt-in, it may take up to 24 hours for the
- app to become available in Google Play Store.</p>
-
-<p>After you install the <em>Android Wear Preview</em> app, you can set up
- your device to communicate with the Android Wear emulator:</p>
-
-<ol>
-<li>Open the <em>Android Wear Preview</em> app. You should see a notice that the app is currently
- not enabled as a notification listener. Tap the message to open the system settings,
- then select Android Wear Preview to grant it notification access.</li>
-<li>Connect your device to your development machine over USB. Be sure that no other
- Android devices are connected to the machine.</li>
-<li>Ensure that the Android Wear emulator (created in the previous section) is running.
-The emulator should show the time and an icon that indicates no device is connected.</li>
-<li>Open a command line terminal, navigate to your Android SDK's <code>platform-tools/</code>
-directory, then execute:
-<pre style="margin-top:.5em">adb -d forward tcp:5601 tcp:5601</pre>
-<p class="note"><strong>Note:</strong> You must execute this command each time you connect your
-device over USB.</p>
-</li>
-<li>Return to the Android Wear Preview app. It should now indicate that it is connected to
- the emulator. The Android Wear emulator should now show the 'g' orb icon, indicating
- that is is connected to your device.
-</ol>
-
-<p>Now, notifications from your device also appear in the Android Wear emulator.</p>
-
-
-
-
-<h2 id="AddLibrary">4. Add the Support Library to Your Project</h2>
-
-<p>The Android Wear preview support library includes several APIs that allow you to
-optimize your app's notifications for the Android Wear user experience.</p>
-
-<p>To receive the preview support library, you must <a
-href="/wear/preview/signup.html">sign up for the Developer Preview</a>. The
-confirmation email you receive after you sign up includes a link to download a ZIP file,
-which contains the preview support library and some sample apps.</p>
-
-<p>After you download and unzip the package, add the preview support library
-sto your Android project:</p>
-
-<p><b>If you're using Eclipse:</b></p>
- <ol>
- <li>In your Android app project, create a <code>libs/</code> directory in your project root
- (the same location as the <code>AndroidManifest.xml</code> file).</li>
- <li>Copy the v4 support library JAR file from your Android SDK directory (e.g.,
- <code>&lt;sdk&gt;/extras/android/support/v4/android-support-v4.jar</code>) into your
- project <code>libs/</code> directory.
- <li>Also save the <code>wearable-preview-support.jar</code> file in the <code>libs/</code> directory.
- <li>Right click each JAR file and select <strong>Build Path &gt; Add to Build Path</strong>.</li>
- </ol>
-
- <p><b>If you're using Android Studio:</b></p>
- <ol>
- <li>In your Android app project, create a <code>libs/</code> directory in your project root
- (the same location as the <code>AndroidManifest.xml</code> file).</li>
- <li>Save the <code>wearable-preview-support.jar</code> file in the <code>libs/</code> directory.
- <li>Open the <code>build.gradle</code> file in your app module.</li>
- <li>Add a dependency rule for both the v4 support library and the Android Wear
- preview support library:
-<pre>
-dependencies {
- compile "com.android.support:support-v4:18.0.+"
- compile files('../libs/wearable-preview-support.jar')
-}
-</pre>
- </li>
- <li>Click <strong>Sync Project with Gradle Files</strong> in the toolbar.</li>
- </ol>
-
-<p>To start optimizing your notifications for Android Wear,
- read <a href="/wear/notifications/creating.html"
- >Creating Notifications for Android Wear</a>.</p>
-
-
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
- <a href="/legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/preview/start.jd b/docs/html/wear/preview/start.jd
new file mode 100644
index 0000000..f8f0129
--- /dev/null
+++ b/docs/html/wear/preview/start.jd
@@ -0,0 +1,254 @@
+page.title=Get Started with the Developer Preview
+
+@jd:body
+
+
+<div class="cols">
+
+ <div class="col-5">
+<p>The Android Wear Developer Preview includes tools and APIs that allow you to
+enhance your app notifications
+to provide an optimized user experience on Android wearables.</p>
+
+<p>With the Android Wear Developer Preview, you can:</p>
+
+<ul>
+ <li>Run the Android Wear platform in the Android emulator.</li>
+ <li>Connect your Android device to the emulator and view notifications from the
+device as cards on Android Wear.</li>
+ <li>Try new APIs in the preview support library that enhance your app's notifications
+with features such as voice replies and notification pages.</li>
+</ul>
+
+<p>To get access to the Developer Preview tools,
+click the sign up button on the right, then follow the setup instructions below.</p>
+ </div>
+
+ <div class="col-7">
+<img src="/wear/images/laptop-bridge.png" width="400" height="222" alt="" />
+
+<a href="/wear/preview/signup.html" class="button" style="
+ width: 370px;
+ margin: 10px 0 20px;
+ font-weight: bold;
+ font-size: 16px;
+">Sign Up for the Developer Preview</a>
+
+<p>Signing up provides you access to:</p>
+<ul>
+<li>New notification APIs in the preview support library.</li>
+<li>Sample apps using the new notification APIs.</li>
+<li>The <em>Android Wear Preview</em> app for your mobile device, which connects
+your device to the Android Wear emulator.</li>
+</ul>
+
+ </div>
+</div>
+
+
+<p class="caution"><strong>Caution:</strong>
+The current Android Wear Developer Preview is intended for <b>development and testing purposes only</b>, not for production apps. Google may change this Developer Preview significantly prior to the official release of the Android Wear SDK. You may not publicly distribute or ship any application using this Developer Preview, as this Developer Preview will no longer be supported after the official SDK is released (which will cause applications based only on the Developer Preview to break).</p>
+
+
+
+
+<h2 id="Prereq">Prerequisites</h2>
+
+<p>Before you begin the setup, you must:</p>
+
+<ol>
+ <li><a href="{@docRoot}sdk/index.html"><b>Install the Android SDK</b></a>.
+ <p>The Android SDK includes all the developer tools required to build
+apps for Android (optional IDEs are also available for download).</p></li>
+ <li><a href="{@docRoot}wear/preview/signup.html"><b>Sign up for the Android Wear Developer Preview</b></a>.
+ <p>You must sign up with a Gmail or other Google account in order to download the
+preview support library and receive access to the
+<em>Android Wear Preview</em> beta app on Google Play Store.</p></li>
+</ol>
+
+<p class="note"><strong>Note:</strong>
+If you're using the ADT plugin for Eclipse, you must update to version 22.6.1 or higher.
+If you're using Android Studio, you must update to version 0.5.1 or higher</p>
+
+
+
+<h2 id="Install">1. Install the Android Wear System Image</h2>
+
+
+<ol>
+ <li>Launch <a href="{@docRoot}tools/help/sdk-manager.html"
+ >Android SDK Manager</a>.
+ <ul>
+ <li>From Eclipse, select <b>Window > Android SDK Manager</b>.</li>
+ <li>From Android Studio, select <b>Tools > Android > SDK Manager</b>.</li>
+ </ul>
+ </li>
+ <li>Below Tools, verify that you have Android SDK Tools revision 22.6 or higher.
+ <p>If your version of Android SDK Tools is lower than 22.6, you must update:</p>
+ <ol>
+ <li>Select <strong>Android SDK Tools</strong>.</li>
+ <li>Click <strong>Install package</strong>.</li>
+ <li>Accept the license and click <strong>Install</strong>.</li>
+ <li>When the installation completes, restart Android SDK Manager.</li>
+ </ol>
+ </li>
+
+ <li>Below Android 4.4.2, select <strong>Android Wear ARM EABI v7a System Image</strong>.
+<p class="note"><strong>Note:</strong> Android Wear is designed to support multiple processor architectures.
+</p></li>
+ <li>Below Extras, ensure that you have the latest version of the
+<a href="{@docRoot}tools/support-library/index.html">Android Support Library</a>.
+ If an update is available, select <strong>Android Support Library</strong>. If you're using Android Studio, also select <strong>Android Support Repository</strong>.</li>
+ <li>Click <strong>Install packages</strong>.</li>
+ <li>Accept the license and click <strong>Install</strong>.</li>
+</ol>
+
+
+
+<h2 id="SetupEmulator">2. Set Up the Android Wear Emulator</h2>
+
+<ol>
+<li>Launch the <a href="{@docRoot}tools/help/avd-manager.html"
+ >Android Virtual Device Manager</a>.
+<ul>
+<li>From Eclipse, select <b>Window > Android Virtual Device Manager</b>.</li>
+<li>From Android Studio, select <b>Tools > Android > AVD Manager</b>.</li>
+</ul>
+</li>
+<li>Click <strong>New</strong>.</li>
+<li>For the AVD Name, enter "AndroidWearSquare" or "AndroidWearRound", depending on whether
+you want to create an emulator with a square or round display.</li>
+<li>For the Device, select <strong>Android Wear Square</strong> or
+ <strong>Android Wear Round</strong>.</li>
+<li>For the Target, select <strong>Android 4.4.2 - API Level 19</strong> (or higher).</li>
+<li>For the CPU/ABI, select <strong>Android Wear ARM (armeabi-v7a)</strong>.
+<p class="note"><strong>Note:</strong> Android Wear is designed to support multiple processor architectures.
+</p></li>
+<li>For the Skin, select <strong>AndroidWearSquare</strong> or
+<strong>AndroidWearRound</strong>.</li>
+<li>Leave all other options set to their defaults and click <strong>OK</strong>.
+ <p>Although real Android wearables do not provide a keyboard as an input method,
+ you should keep <strong>Hardware keyboard present</strong> selected so you can
+ provide text input on screens where users will instead provide voice input.</p>
+</li>
+<!--
+<li>Click <strong>Device Definitions</strong>.</li>
+<li>Select <strong>Android WearSquare</strong> then click <strong>Create AVD</strong>.</li>
+<li>Click <strong>OK</strong>.</li>
+-->
+<li>In the list of AVDs, select the one you just created and click
+ <strong>Start</strong>. In the following window, click <strong>Launch</strong>.</li>
+</ol>
+
+<p>The Android Wear emulator now starts. To begin testing your app's notifications,
+you must now pair the emulator to your development device
+that has the <em>Android Wear Preview</em> app installed.</p>
+
+<p class="note"><strong>Tip:</strong> To improve the emulator startup time, edit your AVD
+and enable <strong>Snapshot</strong> under Emulator Options. When you start the emulator,
+select <strong>Save to snapshot</strong> then click <strong>Launch</strong>. Once the emulator
+is running, close it to save a snapshot of the system.
+Start the AVD again, but select <strong>Launch from snapshot</strong> and
+deselect <strong>Save to snapshot</strong>.</p>
+
+<p class="caution"><strong>Caution:</strong> Do not install apps on the Android Wear emulator.
+The system does not support traditional Android apps and the result of running such apps is
+unpredictable.</p>
+
+
+
+<h2 id="SetupApp">3. Set Up the Android Wear Preview App</h2>
+
+<p>To view your app's notifications on the Android Wear emulator, you must have the
+<em>Android Wear Preview</em> app installed on your Android device (a phone or tablet).</p>
+
+<p>To receive the Android Wear Preview app, you must <a
+href="{@docRoot}wear/preview/signup.html">sign up for the Developer Preview</a> using the same
+Gmail or Google account you use with Google Play Store.</p>
+</p>
+
+<p class="note"><strong>Note:</strong> The <em>Android Wear Preview</em> app is compatible with
+ Android 4.3 and higher and is not available for the Android emulator.</p>
+
+<p>After you've signed up for the Developer Preview,
+ you'll receive a confirmation email that includes a link to opt-in to the
+ <em>Android Wear Preview</em> app beta program. Once you opt-in, it may take up to 24 hours for the
+ app to become available in Google Play Store.</p>
+
+<p>After you install the <em>Android Wear Preview</em> app, you can set up
+ your device to communicate with the Android Wear emulator:</p>
+
+<ol>
+<li>Open the <em>Android Wear Preview</em> app. You should see a notice that the app is currently
+ not enabled as a notification listener. Tap the message to open the system settings,
+ then select Android Wear Preview to grant it notification access.</li>
+<li>Connect your device to your development machine over USB. Be sure that no other
+ Android devices are connected to the machine.</li>
+<li>Ensure that the Android Wear emulator (created in the previous section) is running.
+The emulator should show the time and an icon that indicates no device is connected.</li>
+<li>Open a command line terminal, navigate to your Android SDK's <code>platform-tools/</code>
+directory, then execute:
+<pre style="margin-top:.5em">adb -d forward tcp:5601 tcp:5601</pre>
+<p class="note"><strong>Note:</strong> You must execute this command each time you connect your
+device over USB.</p>
+</li>
+<li>Return to the Android Wear Preview app. It should now indicate that it is connected to
+ the emulator. The Android Wear emulator should now show the 'g' orb icon, indicating
+ that is is connected to your device.
+</ol>
+
+<p>Now, notifications from your device also appear in the Android Wear emulator.</p>
+
+
+
+
+<h2 id="AddLibrary">4. Add the Support Library to Your Project</h2>
+
+<p>The Android Wear preview support library includes several APIs that allow you to
+optimize your app's notifications for the Android Wear user experience.</p>
+
+<p>To receive the preview support library, you must <a
+href="{@docRoot}wear/preview/signup.html">sign up for the Developer Preview</a>. The
+confirmation email you receive after you sign up includes a link to download a ZIP file,
+which contains the preview support library and some sample apps.</p>
+
+<p>After you download and unzip the package, add the preview support library
+sto your Android project:</p>
+
+<p><b>If you're using Eclipse:</b></p>
+ <ol>
+ <li>In your Android app project, create a <code>libs/</code> directory in your project root
+ (the same location as the <code>AndroidManifest.xml</code> file).</li>
+ <li>Copy the v4 support library JAR file from your Android SDK directory (e.g.,
+ <code>&lt;sdk&gt;/extras/android/support/v4/android-support-v4.jar</code>) into your
+ project <code>libs/</code> directory.
+ <li>Also save the <code>wearable-preview-support.jar</code> file in the <code>libs/</code> directory.
+ <li>Right click each JAR file and select <strong>Build Path &gt; Add to Build Path</strong>.</li>
+ </ol>
+
+ <p><b>If you're using Android Studio:</b></p>
+ <ol>
+ <li>In your Android app project, create a <code>libs/</code> directory in your project root
+ (the same location as the <code>AndroidManifest.xml</code> file).</li>
+ <li>Save the <code>wearable-preview-support.jar</code> file in the <code>libs/</code> directory.
+ <li>Open the <code>build.gradle</code> file in your app module.</li>
+ <li>Add a dependency rule for both the v4 support library and the Android Wear
+ preview support library:
+<pre>
+dependencies {
+ compile "com.android.support:support-v4:18.0.+"
+ compile files('../libs/wearable-preview-support.jar')
+}
+</pre>
+ </li>
+ <li>Click <strong>Sync Project with Gradle Files</strong> in the toolbar.</li>
+ </ol>
+
+<p>To start optimizing your notifications for Android Wear,
+ read <a href="{@docRoot}wear/notifications/creating.html"
+ >Creating Notifications for Android Wear</a>.</p>
+
+
+
+</body>
+</html>
diff --git a/docs/html/wear/wear_toc.cs b/docs/html/wear/wear_toc.cs
new file mode 100644
index 0000000..65ac2e9
--- /dev/null
+++ b/docs/html/wear/wear_toc.cs
@@ -0,0 +1,74 @@
+<ul id="nav">
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/preview/start.html">Get Started
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/design/user-interface.html">UI Overview
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/design/index.html">Design Principles
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/creating.html">Creating Notifications for Android Wear
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/remote-input.html">Receiving Voice Input from a Notification
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/pages.html">Adding Pages to a Notification
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/stacks.html">Stacking Notifications
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header"><a href="<?cs var:toroot ?>reference/android/preview/support/package-summary.html">Notification Reference</a></div>
+ <ul class="tree-list-children">
+<li class="nav-section">
+<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
+ <ul>
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
+ </ul>
+</li>
+
+<li class="nav-section">
+<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
+<ul>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
+ </ul>
+ </li>
+</ul>
+</li>
+
+
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/license.html">License Agreement</a></div>
+ </li>
+
+
+</ul>
diff --git a/graphics/java/android/graphics/TemporaryBuffer.java b/graphics/java/android/graphics/TemporaryBuffer.java
index c5b8143..36a2275 100644
--- a/graphics/java/android/graphics/TemporaryBuffer.java
+++ b/graphics/java/android/graphics/TemporaryBuffer.java
@@ -31,7 +31,7 @@ public class TemporaryBuffer {
}
if (buf == null || buf.length < len) {
- buf = new char[ArrayUtils.idealCharArraySize(len)];
+ buf = ArrayUtils.newUnpaddedCharArray(len);
}
return buf;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index de2b68f..e320c67 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1054,14 +1054,14 @@ public abstract class Drawable {
drawable = new LayerDrawable();
} else if (name.equals("transition")) {
drawable = new TransitionDrawable();
- } else if (name.equals("reveal")) {
- drawable = new RevealDrawable();
} else if (name.equals("touch-feedback")) {
drawable = new TouchFeedbackDrawable();
} else if (name.equals("color")) {
drawable = new ColorDrawable();
} else if (name.equals("shape")) {
drawable = new GradientDrawable();
+ } else if (name.equals("vector")) {
+ drawable = new VectorDrawable();
} else if (name.equals("scale")) {
drawable = new ScaleDrawable();
} else if (name.equals("clip")) {
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 3d48cda..3c3c841 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -839,7 +839,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
/**
* Ensures the child padding caches are large enough.
*/
- private void ensurePadding() {
+ void ensurePadding() {
final int N = mLayerState.mNum;
if (mPaddingL != null && mPaddingL.length >= N) {
return;
diff --git a/graphics/java/android/graphics/drawable/RevealDrawable.java b/graphics/java/android/graphics/drawable/RevealDrawable.java
deleted file mode 100644
index 2f96fe4..0000000
--- a/graphics/java/android/graphics/drawable/RevealDrawable.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.drawable;
-
-import android.content.res.Resources;
-import android.content.res.Resources.Theme;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.SparseArray;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-/**
- * An extension of LayerDrawable that is intended to react to touch hotspots
- * and reveal the second layer atop the first.
- * <p>
- * It can be defined in an XML file with the <code>&lt;reveal&gt;</code> element.
- * Each Drawable in the transition is defined in a nested <code>&lt;item&gt;</code>.
- * For more information, see the guide to <a href="{@docRoot}
- * guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
- *
- * @attr ref android.R.styleable#LayerDrawableItem_left
- * @attr ref android.R.styleable#LayerDrawableItem_top
- * @attr ref android.R.styleable#LayerDrawableItem_right
- * @attr ref android.R.styleable#LayerDrawableItem_bottom
- * @attr ref android.R.styleable#LayerDrawableItem_drawable
- * @attr ref android.R.styleable#LayerDrawableItem_id
- */
-public class RevealDrawable extends LayerDrawable {
- private final Rect mTempRect = new Rect();
-
- /** Lazily-created map of touch hotspot IDs to ripples. */
- private SparseArray<Ripple> mTouchedRipples;
-
- /** Lazily-created list of actively animating ripples. */
- private ArrayList<Ripple> mActiveRipples;
-
- /** Lazily-created runnable for scheduling invalidation. */
- private Runnable mAnimationRunnable;
-
- /** Whether the animation runnable has been posted. */
- private boolean mAnimating;
-
- /** Target density, used to scale density-independent pixels. */
- private float mDensity = 1.0f;
-
- /** Paint used to control appearance of ripples. */
- private Paint mRipplePaint;
-
- /** Paint used to control reveal layer masking. */
- private Paint mMaskingPaint;
-
- /**
- * Create a new reveal drawable with the specified list of layers. At least
- * two layers are required for this drawable to work properly.
- */
- public RevealDrawable(Drawable[] layers) {
- this(new RevealState(null, null, null), layers);
- }
-
- /**
- * Create a new reveal drawable with no layers. To work correctly, at least
- * two layers must be added to this drawable.
- *
- * @see #RevealDrawable(Drawable[])
- */
- RevealDrawable() {
- this(new RevealState(null, null, null), (Resources) null, null);
- }
-
- private RevealDrawable(RevealState state, Resources res) {
- super(state, res, null);
- }
-
- private RevealDrawable(RevealState state, Resources res, Theme theme) {
- super(state, res, theme);
- }
-
- private RevealDrawable(RevealState state, Drawable[] layers) {
- super(layers, state);
- }
-
- @Override
- public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
- throws XmlPullParserException, IOException {
- super.inflate(r, parser, attrs, theme);
-
- setTargetDensity(r.getDisplayMetrics());
- setPaddingMode(PADDING_MODE_STACK);
- }
-
- @Override
- LayerState createConstantState(LayerState state, Resources res) {
- return new RevealState((RevealState) state, this, res);
- }
-
- /**
- * Set the density at which this drawable will be rendered.
- *
- * @param metrics The display metrics for this drawable.
- */
- private void setTargetDensity(DisplayMetrics metrics) {
- if (mDensity != metrics.density) {
- mDensity = metrics.density;
- invalidateSelf();
- }
- }
-
- /**
- * @hide until hotspot APIs are finalized
- */
- @Override
- public boolean supportsHotspots() {
- return true;
- }
-
- /**
- * @hide until hotspot APIs are finalized
- */
- @Override
- public void setHotspot(int id, float x, float y) {
- if (mTouchedRipples == null) {
- mTouchedRipples = new SparseArray<Ripple>();
- mActiveRipples = new ArrayList<Ripple>();
- }
-
- final Ripple ripple = mTouchedRipples.get(id);
- if (ripple == null) {
- final Rect padding = mTempRect;
- getPadding(padding);
-
- final Ripple newRipple = new Ripple(getBounds(), padding, x, y, mDensity);
- newRipple.enter();
-
- mActiveRipples.add(newRipple);
- mTouchedRipples.put(id, newRipple);
- } else {
- ripple.move(x, y);
- }
-
- scheduleAnimation();
- }
-
- /**
- * @hide until hotspot APIs are finalized
- */
- @Override
- public void removeHotspot(int id) {
- if (mTouchedRipples == null) {
- return;
- }
-
- final Ripple ripple = mTouchedRipples.get(id);
- if (ripple != null) {
- ripple.exit();
-
- mTouchedRipples.remove(id);
- scheduleAnimation();
- }
- }
-
- /**
- * @hide until hotspot APIs are finalized
- */
- @Override
- public void clearHotspots() {
- if (mTouchedRipples == null) {
- return;
- }
-
- final int n = mTouchedRipples.size();
- for (int i = 0; i < n; i++) {
- final Ripple ripple = mTouchedRipples.valueAt(i);
- ripple.exit();
- }
-
- if (n > 0) {
- mTouchedRipples.clear();
- scheduleAnimation();
- }
- }
-
- /**
- * Schedules the next animation, if necessary.
- */
- private void scheduleAnimation() {
- if (mActiveRipples == null || mActiveRipples.isEmpty()) {
- mAnimating = false;
- } else if (!mAnimating) {
- mAnimating = true;
-
- if (mAnimationRunnable == null) {
- mAnimationRunnable = new Runnable() {
- @Override
- public void run() {
- mAnimating = false;
- scheduleAnimation();
- invalidateSelf();
- }
- };
- }
-
- scheduleSelf(mAnimationRunnable, SystemClock.uptimeMillis() + 1000 / 60);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- final int layerCount = getNumberOfLayers();
- if (layerCount == 0) {
- return;
- }
-
- getDrawable(0).draw(canvas);
-
- final Rect bounds = getBounds();
- final ArrayList<Ripple> activeRipples = mActiveRipples;
- if (layerCount == 1 || bounds.isEmpty() || activeRipples == null
- || activeRipples.isEmpty()) {
- // Nothing to reveal, we're done here.
- return;
- }
-
- if (mRipplePaint == null) {
- mRipplePaint = new Paint();
- mRipplePaint.setAntiAlias(true);
- }
-
- // Draw ripple mask into a buffer that merges using SRC_OVER.
- boolean needsMask = false;
- int layerSaveCount = -1;
- int n = activeRipples.size();
- for (int i = 0; i < n; i++) {
- final Ripple ripple = activeRipples.get(i);
- if (!ripple.active()) {
- activeRipples.remove(i);
- i--;
- n--;
- } else {
- if (layerSaveCount < 0) {
- layerSaveCount = canvas.saveLayer(
- bounds.left, bounds.top, bounds.right, bounds.bottom, null, 0);
- // Ripples must be clipped to bounds, otherwise SRC_IN will
- // miss them and we'll get artifacts.
- canvas.clipRect(bounds);
- }
-
- needsMask |= ripple.draw(canvas, mRipplePaint);
- }
- }
-
- // If a layer was saved, it contains the ripple mask. Draw the reveal
- // into another layer and composite using SRC_IN, then composite onto
- // the original canvas.
- if (layerSaveCount >= 0) {
- if (needsMask) {
- if (mMaskingPaint == null) {
- mMaskingPaint = new Paint();
- mMaskingPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
- }
-
- // TODO: When Drawable.setXfermode() is supported by all drawables,
- // we won't need an extra layer.
- canvas.saveLayer(
- bounds.left, bounds.top, bounds.right, bounds.bottom, mMaskingPaint, 0);
- getDrawable(1).draw(canvas);
- }
-
- canvas.restoreToCount(layerSaveCount);
- }
- }
-
- private static class RevealState extends LayerState {
- public RevealState(RevealState orig, RevealDrawable owner, Resources res) {
- super(orig, owner, res);
- }
-
- @Override
- public Drawable newDrawable() {
- return newDrawable(null);
- }
-
- @Override
- public Drawable newDrawable(Resources res) {
- return new RevealDrawable(this, res);
- }
-
- @Override
- public Drawable newDrawable(Resources res, Theme theme) {
- return new RevealDrawable(this, res, theme);
- }
- }
-}
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 618afb8..03dd841 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -43,34 +43,16 @@ class Ripple {
/** Resistance factor when constraining outside touches. */
private static final float OUTSIDE_RESISTANCE = 0.7f;
- /** Duration for animating the trailing edge of the ripple. */
- private static final int EXIT_DURATION = 600;
-
- /** Duration for animating the leading edge of the ripple. */
- private static final int ENTER_DURATION = 400;
-
- /** Minimum elapsed time between start of enter and exit animations. */
- private static final int EXIT_MIN_DELAY = 200;
-
- /** Duration for animating between inside and outside touch. */
- private static final int OUTSIDE_DURATION = 300;
-
- /** Duration for animating pulses. */
- private static final int PULSE_DURATION = 400;
-
- /** Interval between pulses while inside and fully entered. */
- private static final int PULSE_INTERVAL = 400;
-
/** Minimum alpha value during a pulse animation. */
private static final int PULSE_MIN_ALPHA = 128;
- /** Delay before pulses start. */
- private static final int PULSE_DELAY = 500;
-
private final Rect mBounds;
private final Rect mPadding;
- private final int mMinRadius;
- private final int mOutsideRadius;
+
+ private RippleAnimator mAnimator;
+
+ private int mMinRadius;
+ private int mOutsideRadius;
/** Center x-coordinate. */
private float mX;
@@ -80,15 +62,18 @@ class Ripple {
/** Whether the center is within the parent bounds. */
private boolean mInside;
+
+ /** Enter state. A value in [0...1] or -1 if not set. */
+ private float mEnterState = -1;
- /** When the ripple started appearing. */
- private long mEnterTime = -1;
+ /** Exit state. A value in [0...1] or -1 if not set. */
+ private float mExitState = -1;
- /** When the ripple started vanishing. */
- private long mExitTime = -1;
+ /** Outside state. A value in [0...1] or -1 if not set. */
+ private float mOutsideState = -1;
- /** When the ripple last transitioned between inside and outside touch. */
- private long mOutsideTime = -1;
+ /** Pulse state. A value in [0...1] or -1 if not set. */
+ private float mPulseState = -1;
/**
* Creates a new ripple with the specified parent bounds, padding, initial
@@ -105,6 +90,14 @@ class Ripple {
mMinRadius = (int) (density * STARTING_RADIUS_DP + 0.5f);
mOutsideRadius = (int) (density * OUTSIDE_RADIUS_DP + 0.5f);
}
+
+ public void setMinRadius(int minRadius) {
+ mMinRadius = minRadius;
+ }
+
+ public void setOutsideRadius(int outsideRadius) {
+ mOutsideRadius = outsideRadius;
+ }
/**
* Updates the center coordinates.
@@ -115,49 +108,18 @@ class Ripple {
final boolean inside = mBounds.contains((int) x, (int) y);
if (mInside != inside) {
- mOutsideTime = AnimationUtils.currentAnimationTimeMillis();
+ if (mAnimator != null) {
+ mAnimator.outside();
+ }
mInside = inside;
}
}
- /**
- * Starts the enter animation.
- */
- public void enter() {
- mEnterTime = AnimationUtils.currentAnimationTimeMillis();
- }
-
- /**
- * Starts the exit animation. If {@link #enter()} was called recently, the
- * animation may be postponed.
- */
- public void exit() {
- final long minTime = mEnterTime + EXIT_MIN_DELAY;
- mExitTime = Math.max(minTime, AnimationUtils.currentAnimationTimeMillis());
- }
-
- /**
- * Returns whether this ripple is currently animating.
- */
- public boolean active() {
- final long currentTime = AnimationUtils.currentAnimationTimeMillis();
- return mEnterTime >= 0 && mEnterTime <= currentTime
- && (mExitTime < 0 || currentTime <= mExitTime + EXIT_DURATION);
- }
-
- /**
- * Constrains a value within a specified asymptotic margin outside a minimum
- * and maximum.
- */
- private static float looseConstrain(float value, float min, float max, float margin,
- float factor) {
- if (value < min) {
- return min - Math.min(margin, (float) Math.pow(min - value, factor));
- } else if (value > max) {
- return max + Math.min(margin, (float) Math.pow(value - max, factor));
- } else {
- return value;
+ public RippleAnimator animate() {
+ if (mAnimator == null) {
+ mAnimator = new RippleAnimator(this);
}
+ return mAnimator;
}
public boolean draw(Canvas c, Paint p) {
@@ -167,17 +129,10 @@ class Ripple {
final float dY = Math.max(mY, bounds.bottom - mY);
final int maxRadius = (int) Math.ceil(Math.sqrt(dX * dX + dY * dY));
- // Track three states:
- // - Enter: touch begins, affects outer radius
- // - Outside: touch moves outside bounds, affects maximum outer radius
- // - Exit: touch ends, affects inner radius
- final long currentTime = AnimationUtils.currentAnimationTimeMillis();
- final float enterState = mEnterTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
- MathUtils.constrain((currentTime - mEnterTime) / (float) ENTER_DURATION, 0, 1));
- final float outsideState = mOutsideTime < 0 ? 1 : INTERPOLATOR.getInterpolation(
- MathUtils.constrain((currentTime - mOutsideTime) / (float) OUTSIDE_DURATION, 0, 1));
- final float exitState = mExitTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
- MathUtils.constrain((currentTime - mExitTime) / (float) EXIT_DURATION, 0, 1));
+ final float enterState = mEnterState;
+ final float exitState = mExitState;
+ final float outsideState = mOutsideState;
+ final float pulseState = mPulseState;
final float insideRadius = MathUtils.lerp(mMinRadius, maxRadius, enterState);
final float outerRadius = MathUtils.lerp(mOutsideRadius, insideRadius,
mInside ? outsideState : 1 - outsideState);
@@ -189,35 +144,28 @@ class Ripple {
outerRadius * OUTSIDE_MARGIN, OUTSIDE_RESISTANCE);
// Compute maximum alpha, taking pulse into account when active.
- final long pulseTime = (currentTime - mEnterTime - ENTER_DURATION - PULSE_DELAY);
final int maxAlpha;
- if (pulseTime < 0) {
+ if (pulseState < 0 || pulseState >= 1) {
maxAlpha = 255;
} else {
- final float pulseState = (pulseTime % (PULSE_INTERVAL + PULSE_DURATION))
- / (float) PULSE_DURATION;
- if (pulseState >= 1) {
- maxAlpha = 255;
+ final float pulseAlpha;
+ if (pulseState > 0.5) {
+ // Pulsing in to max alpha.
+ pulseAlpha = MathUtils.lerp(PULSE_MIN_ALPHA, 255, (pulseState - .5f) * 2);
} else {
- final float pulseAlpha;
- if (pulseState > 0.5) {
- // Pulsing in to max alpha.
- pulseAlpha = MathUtils.lerp(PULSE_MIN_ALPHA, 255, (pulseState - .5f) * 2);
- } else {
- // Pulsing out to min alpha.
- pulseAlpha = MathUtils.lerp(255, PULSE_MIN_ALPHA, pulseState * 2f);
- }
+ // Pulsing out to min alpha.
+ pulseAlpha = MathUtils.lerp(255, PULSE_MIN_ALPHA, pulseState * 2f);
+ }
- if (exitState > 0) {
- // Animating exit, interpolate pulse with exit state.
- maxAlpha = (int) (MathUtils.lerp(255, pulseAlpha, exitState) + 0.5f);
- } else if (mInside) {
- // No animation, no need to interpolate.
- maxAlpha = (int) (pulseAlpha + 0.5f);
- } else {
- // Animating inside, interpolate pulse with inside state.
- maxAlpha = (int) (MathUtils.lerp(pulseAlpha, 255, outsideState) + 0.5f);
- }
+ if (exitState > 0) {
+ // Animating exit, interpolate pulse with exit state.
+ maxAlpha = (int) (MathUtils.lerp(255, pulseAlpha, exitState) + 0.5f);
+ } else if (mInside) {
+ // No animation, no need to interpolate.
+ maxAlpha = (int) (pulseAlpha + 0.5f);
+ } else {
+ // Animating inside, interpolate pulse with inside state.
+ maxAlpha = (int) (MathUtils.lerp(pulseAlpha, 255, outsideState) + 0.5f);
}
}
@@ -260,4 +208,109 @@ class Ripple {
final int maxRadius = (int) Math.ceil(Math.sqrt(dX * dX + dY * dY));
bounds.set(x - maxRadius, y - maxRadius, x + maxRadius, y + maxRadius);
}
+
+ /**
+ * Constrains a value within a specified asymptotic margin outside a minimum
+ * and maximum.
+ */
+ private static float looseConstrain(float value, float min, float max, float margin,
+ float factor) {
+ if (value < min) {
+ return min - Math.min(margin, (float) Math.pow(min - value, factor));
+ } else if (value > max) {
+ return max + Math.min(margin, (float) Math.pow(value - max, factor));
+ } else {
+ return value;
+ }
+ }
+
+ public static class RippleAnimator {
+ /** Duration for animating the trailing edge of the ripple. */
+ private static final int EXIT_DURATION = 600;
+
+ /** Duration for animating the leading edge of the ripple. */
+ private static final int ENTER_DURATION = 400;
+
+ /** Minimum elapsed time between start of enter and exit animations. */
+ private static final int EXIT_MIN_DELAY = 200;
+
+ /** Duration for animating between inside and outside touch. */
+ private static final int OUTSIDE_DURATION = 300;
+
+ /** Duration for animating pulses. */
+ private static final int PULSE_DURATION = 400;
+
+ /** Interval between pulses while inside and fully entered. */
+ private static final int PULSE_INTERVAL = 400;
+
+ /** Delay before pulses start. */
+ private static final int PULSE_DELAY = 500;
+
+ /** The target ripple being animated. */
+ private final Ripple mTarget;
+
+ /** When the ripple started appearing. */
+ private long mEnterTime = -1;
+
+ /** When the ripple started vanishing. */
+ private long mExitTime = -1;
+
+ /** When the ripple last transitioned between inside and outside touch. */
+ private long mOutsideTime = -1;
+
+ public RippleAnimator(Ripple target) {
+ mTarget = target;
+ }
+
+ /**
+ * Starts the enter animation.
+ */
+ public void enter() {
+ mEnterTime = AnimationUtils.currentAnimationTimeMillis();
+ }
+
+ /**
+ * Starts the exit animation. If {@link #enter()} was called recently, the
+ * animation may be postponed.
+ */
+ public void exit() {
+ final long minTime = mEnterTime + EXIT_MIN_DELAY;
+ mExitTime = Math.max(minTime, AnimationUtils.currentAnimationTimeMillis());
+ }
+
+ /**
+ * Starts the outside transition animation.
+ */
+ public void outside() {
+ mOutsideTime = AnimationUtils.currentAnimationTimeMillis();
+ }
+
+ /**
+ * Returns whether this ripple is currently animating.
+ */
+ public boolean isRunning() {
+ final long currentTime = AnimationUtils.currentAnimationTimeMillis();
+ return mEnterTime >= 0 && mEnterTime <= currentTime
+ && (mExitTime < 0 || currentTime <= mExitTime + EXIT_DURATION);
+ }
+
+ public void update() {
+ // Track three states:
+ // - Enter: touch begins, affects outer radius
+ // - Outside: touch moves outside bounds, affects maximum outer radius
+ // - Exit: touch ends, affects inner radius
+ final long currentTime = AnimationUtils.currentAnimationTimeMillis();
+ mTarget.mEnterState = mEnterTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
+ MathUtils.constrain((currentTime - mEnterTime) / (float) ENTER_DURATION, 0, 1));
+ mTarget.mExitState = mExitTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
+ MathUtils.constrain((currentTime - mExitTime) / (float) EXIT_DURATION, 0, 1));
+ mTarget.mOutsideState = mOutsideTime < 0 ? 1 : INTERPOLATOR.getInterpolation(
+ MathUtils.constrain((currentTime - mOutsideTime) / (float) OUTSIDE_DURATION, 0, 1));
+
+ // Pulse is a little more complicated.
+ final long pulseTime = (currentTime - mEnterTime - ENTER_DURATION - PULSE_DELAY);
+ mTarget.mPulseState = pulseTime < 0 ? -1
+ : (pulseTime % (PULSE_INTERVAL + PULSE_DURATION)) / (float) PULSE_DURATION;
+ }
+ }
}
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index 47a9374..64de95f 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -25,6 +25,7 @@ import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.Ripple.RippleAnimator;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.os.SystemClock;
@@ -38,12 +39,17 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
-import java.util.ArrayList;
/**
* Documentation pending.
*/
-public class TouchFeedbackDrawable extends DrawableWrapper {
+public class TouchFeedbackDrawable extends LayerDrawable {
+ private static final PorterDuffXfermode DST_ATOP = new PorterDuffXfermode(Mode.DST_ATOP);
+ private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(Mode.DST_IN);
+
+ /** The maximum number of ripples supported. */
+ private static final int MAX_RIPPLES = 10;
+
private final Rect mTempRect = new Rect();
private final Rect mPaddingRect = new Rect();
@@ -58,8 +64,9 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
/** Lazily-created map of touch hotspot IDs to ripples. */
private SparseArray<Ripple> mTouchedRipples;
- /** Lazily-created list of actively animating ripples. */
- private ArrayList<Ripple> mActiveRipples;
+ /** Lazily-created array of actively animating ripples. */
+ private Ripple[] mActiveRipples;
+ private int mActiveRipplesCount = 0;
/** Lazily-created runnable for scheduling invalidation. */
private Runnable mAnimationRunnable;
@@ -76,50 +83,21 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
/** Whether the animation runnable has been posted. */
private boolean mAnimating;
- /** The drawable to use as the mask. */
- private Drawable mMask;
-
TouchFeedbackDrawable() {
- this(new TouchFeedbackState(null), null, null);
- }
-
- private void setConstantState(TouchFeedbackState wrapperState, Resources res) {
- super.setConstantState(wrapperState, res);
-
- // Load a new mask drawable from the constant state.
- if (wrapperState == null || wrapperState.mMaskState == null) {
- mMask = null;
- } else if (res != null) {
- mMask = wrapperState.mMaskState.newDrawable(res);
- } else {
- mMask = wrapperState.mMaskState.newDrawable();
- }
-
- if (res != null) {
- mDensity = res.getDisplayMetrics().density;
- }
+ this(new TouchFeedbackState(null, null, null), null, null);
}
@Override
public int getOpacity() {
- return mActiveRipples != null && !mActiveRipples.isEmpty() ?
- PixelFormat.TRANSLUCENT : PixelFormat.TRANSPARENT;
- }
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- super.onBoundsChange(bounds);
-
- if (mMask != null) {
- mMask.setBounds(bounds);
- }
+ // Worst-case scenario.
+ return PixelFormat.TRANSLUCENT;
}
@Override
protected boolean onStateChange(int[] stateSet) {
super.onStateChange(stateSet);
- if (mRipplePaint != null) {
+ if (mRipplePaint != null && mState.mTint != null) {
final ColorStateList stateList = mState.mTint;
final int newColor = stateList.getColorForState(stateSet, 0);
final int oldColor = mRipplePaint.getColor();
@@ -138,77 +116,39 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
*/
@Override
public boolean isProjected() {
- return mState.mProjected;
+ return getNumberOfLayers() == 0;
}
@Override
public boolean isStateful() {
- return super.isStateful() || mState.mTint.isStateful();
+ return super.isStateful() || mState.mTint != null && mState.mTint.isStateful();
}
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- super.inflate(r, parser, attrs, theme);
-
final TypedArray a = obtainAttributes(
r, theme, attrs, R.styleable.TouchFeedbackDrawable);
- inflateStateFromTypedArray(r, a);
+ inflateStateFromTypedArray(a);
a.recycle();
-
- inflateChildElements(r, parser, attrs, theme);
-
- setTargetDensity(r.getDisplayMetrics());
- }
-
- private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
- Theme theme) throws XmlPullParserException, IOException {
- int type;
- while ((type = parser.next()) == XmlPullParser.TEXT) {
- // Find the next non-text element.
- }
-
- if (type == XmlPullParser.START_TAG) {
- final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs);
- setDrawable(dr, r);
- }
- }
- /**
- * Sets the wrapped drawable and update the constant state.
- *
- * @param drawable
- * @param res
- */
- void setMaskDrawable(Drawable drawable, Resources res) {
- mMask = drawable;
-
- if (drawable != null) {
- // Nobody cares if the mask has a callback.
- drawable.setCallback(null);
+ super.inflate(r, parser, attrs, theme);
- mState.mMaskState = drawable.getConstantState();
- } else {
- mState.mMaskState = null;
- }
+ setTargetDensity(r.getDisplayMetrics());
}
/**
* Initializes the constant state from the values in the typed array.
*/
- private void inflateStateFromTypedArray(Resources r, TypedArray a) {
+ private void inflateStateFromTypedArray(TypedArray a) {
final TouchFeedbackState state = mState;
// Extract the theme attributes, if any.
final int[] themeAttrs = a.extractThemeAttrs();
- state.mThemeAttrs = themeAttrs;
+ state.mTouchThemeAttrs = themeAttrs;
if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_tint] == 0) {
mState.mTint = a.getColorStateList(R.styleable.TouchFeedbackDrawable_tint);
-
- if (mState.mTint == null) {
- throw new RuntimeException("<touch-feedback> tag requires a 'tint' attribute");
- }
}
if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_tintMode] == 0) {
@@ -219,34 +159,6 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_pinned] == 0) {
mState.mPinned = a.getBoolean(R.styleable.TouchFeedbackDrawable_pinned, false);
}
-
- Drawable mask = mMask;
- if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_mask] == 0) {
- mask = a.getDrawable(R.styleable.TouchFeedbackDrawable_mask);
- }
-
- Drawable dr = super.getDrawable();
- if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_drawable] == 0) {
- final int drawableRes = a.getResourceId(R.styleable.TouchFeedbackDrawable_drawable, 0);
- if (drawableRes != 0) {
- dr = r.getDrawable(drawableRes);
- }
- }
-
- // If neither a mask not a bottom layer was specified, assume we're
- // projecting onto a parent surface.
- mState.mProjected = mask == null && dr == null;
-
- if (dr != null) {
- setDrawable(dr, r);
- } else {
- // For now at least, we MUST have a wrapped drawable.
- setDrawable(new ColorDrawable(Color.TRANSPARENT), r);
- }
-
- if (mask != null) {
- setMaskDrawable(mask, r);
- }
}
/**
@@ -271,7 +183,7 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
"Can't apply theme to <touch-feedback> with no constant state");
}
- final int[] themeAttrs = state.mThemeAttrs;
+ final int[] themeAttrs = state.mTouchThemeAttrs;
if (themeAttrs != null) {
final TypedArray a = t.resolveAttributes(
themeAttrs, R.styleable.TouchFeedbackDrawable, 0, 0);
@@ -298,39 +210,11 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
if (a.hasValue(R.styleable.TouchFeedbackDrawable_pinned)) {
mState.mPinned = a.getBoolean(R.styleable.TouchFeedbackDrawable_pinned, false);
}
-
- Drawable mask = mMask;
- if (a.hasValue(R.styleable.TouchFeedbackDrawable_mask)) {
- mask = a.getDrawable(R.styleable.TouchFeedbackDrawable_mask);
- }
-
- Drawable dr = super.getDrawable();
- if (a.hasValue(R.styleable.TouchFeedbackDrawable_drawable)) {
- final int drawableRes = a.getResourceId(R.styleable.TouchFeedbackDrawable_drawable, 0);
- if (drawableRes != 0) {
- dr = a.getResources().getDrawable(drawableRes);
- }
- }
-
- // If neither a mask not a bottom layer was specified, assume we're
- // projecting onto a parent surface.
- mState.mProjected = mask == null && dr == null;
-
- if (dr != null) {
- setDrawable(dr, a.getResources());
- } else {
- // For now at least, we MUST have a wrapped drawable.
- setDrawable(new ColorDrawable(Color.TRANSPARENT), a.getResources());
- }
-
- if (mask != null) {
- setMaskDrawable(mask, a.getResources());
- }
}
@Override
public boolean canApplyTheme() {
- return mState != null && mState.mThemeAttrs != null;
+ return super.canApplyTheme() || mState != null && mState.mTouchThemeAttrs != null;
}
/**
@@ -351,7 +235,7 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
public void setHotspot(int id, float x, float y) {
if (mTouchedRipples == null) {
mTouchedRipples = new SparseArray<Ripple>();
- mActiveRipples = new ArrayList<Ripple>();
+ mActiveRipples = new Ripple[MAX_RIPPLES];
}
final Ripple ripple = mTouchedRipples.get(id);
@@ -366,9 +250,9 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
}
final Ripple newRipple = new Ripple(bounds, padding, x, y, mDensity);
- newRipple.enter();
+ newRipple.animate().enter();
- mActiveRipples.add(newRipple);
+ mActiveRipples[mActiveRipplesCount++] = newRipple;
mTouchedRipples.put(id, newRipple);
} else if (!mState.mPinned) {
ripple.move(x, y);
@@ -388,7 +272,7 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
final Ripple ripple = mTouchedRipples.get(id);
if (ripple != null) {
- ripple.exit();
+ ripple.animate().exit();
mTouchedRipples.remove(id);
scheduleAnimation();
@@ -406,8 +290,7 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
final int n = mTouchedRipples.size();
for (int i = 0; i < n; i++) {
- final Ripple ripple = mTouchedRipples.valueAt(i);
- ripple.exit();
+ mTouchedRipples.valueAt(i).animate().exit();
}
if (n > 0) {
@@ -420,7 +303,7 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
* Schedules the next animation, if necessary.
*/
private void scheduleAnimation() {
- if (mActiveRipples == null || mActiveRipples.isEmpty()) {
+ if (mActiveRipplesCount == 0) {
mAnimating = false;
} else if (!mAnimating) {
mAnimating = true;
@@ -442,53 +325,68 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
@Override
public void draw(Canvas canvas) {
- // The lower layer always draws normally.
- super.draw(canvas);
+ final boolean projected = getNumberOfLayers() == 0;
+ final Ripple[] activeRipples = mActiveRipples;
+ final int ripplesCount = mActiveRipplesCount;
+ final Rect bounds = getBounds();
- if (mActiveRipples == null || mActiveRipples.size() == 0) {
- // No ripples to draw.
- return;
- }
-
- final ArrayList<Ripple> activeRipples = mActiveRipples;
- final Drawable mask = mMask == null && !mState.mProjected ? getDrawable() : null;
- final Rect bounds = mask == null ? null : mask.getBounds();
-
- // Draw ripples into a layer that merges using SRC_IN.
- boolean hasRipples = false;
+ // Draw ripples.
+ boolean drewRipples = false;
int rippleRestoreCount = -1;
- int n = activeRipples.size();
- for (int i = 0; i < n; i++) {
- final Ripple ripple = activeRipples.get(i);
- if (!ripple.active()) {
- // TODO: Mark and sweep is more efficient.
- activeRipples.remove(i);
- i--;
- n--;
+ int activeRipplesCount = 0;
+ for (int i = 0; i < ripplesCount; i++) {
+ final Ripple ripple = activeRipples[i];
+ final RippleAnimator animator = ripple.animate();
+ animator.update();
+ if (!animator.isRunning()) {
+ activeRipples[i] = null;
} else {
- // If we're masking the ripple layer, make sure we have a layer first.
- if (mask != null && rippleRestoreCount < 0) {
+ // If we're masking the ripple layer, make sure we have a layer
+ // first. This will merge SRC_OVER (directly) onto the canvas.
+ if (!projected && rippleRestoreCount < 0) {
rippleRestoreCount = canvas.saveLayer(bounds.left, bounds.top,
- bounds.right, bounds.bottom, getMaskingPaint(SRC_ATOP), 0);
+ bounds.right, bounds.bottom, null, 0);
canvas.clipRect(bounds);
}
- hasRipples |= ripple.draw(canvas, getRipplePaint());
+ drewRipples |= ripple.draw(canvas, getRipplePaint());
+
+ activeRipples[activeRipplesCount] = activeRipples[i];
+ activeRipplesCount++;
+ }
+ }
+ mActiveRipplesCount = activeRipplesCount;
+
+ // TODO: Use the masking layer first, if there is one.
+
+ // If we have ripples and content, we need a masking layer. This will
+ // merge DST_ATOP onto (effectively under) the ripple layer.
+ if (drewRipples && !projected && rippleRestoreCount >= 0) {
+ canvas.saveLayer(bounds.left, bounds.top,
+ bounds.right, bounds.bottom, getMaskingPaint(DST_ATOP), 0);
+ }
+
+ Drawable mask = null;
+ final ChildDrawable[] array = mLayerState.mChildren;
+ final int N = mLayerState.mNum;
+ for (int i = 0; i < N; i++) {
+ if (array[i].mId != R.id.mask) {
+ array[i].mDrawable.draw(canvas);
+ } else {
+ mask = array[i].mDrawable;
}
}
// If we have ripples, mask them.
- if (mask != null && hasRipples) {
+ if (mask != null && drewRipples) {
+ // TODO: This will also mask the lower layer, which is bad.
canvas.saveLayer(bounds.left, bounds.top, bounds.right,
bounds.bottom, getMaskingPaint(DST_IN), 0);
mask.draw(canvas);
}
- // Composite the layers if needed:
- // 1. Mask DST_IN
- // 2. Ripples SRC_ATOP
- // 3. Lower n/a
- if (rippleRestoreCount > 0) {
+ // Composite the layers if needed.
+ if (rippleRestoreCount >= 0) {
canvas.restoreToCount(rippleRestoreCount);
}
}
@@ -497,15 +395,14 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
if (mRipplePaint == null) {
mRipplePaint = new Paint();
mRipplePaint.setAntiAlias(true);
-
- final int color = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
- mRipplePaint.setColor(color);
+
+ if (mState.mTint != null) {
+ final int color = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
+ mRipplePaint.setColor(color);
+ }
}
return mRipplePaint;
}
-
- private static final PorterDuffXfermode SRC_ATOP = new PorterDuffXfermode(Mode.SRC_ATOP);
- private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(Mode.DST_IN);
private Paint getMaskingPaint(PorterDuffXfermode mode) {
if (mMaskingPaint == null) {
@@ -521,15 +418,12 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
final Rect drawingBounds = mDrawingBounds;
dirtyBounds.set(drawingBounds);
drawingBounds.setEmpty();
-
final Rect rippleBounds = mTempRect;
- final ArrayList<Ripple> activeRipples = mActiveRipples;
- if (activeRipples != null) {
- final int N = activeRipples.size();
- for (int i = 0; i < N; i++) {
- activeRipples.get(i).getBounds(rippleBounds);
- drawingBounds.union(rippleBounds);
- }
+ final Ripple[] activeRipples = mActiveRipples;
+ final int N = mActiveRipplesCount;
+ for (int i = 0; i < N; i++) {
+ activeRipples[i].getBounds(rippleBounds);
+ drawingBounds.union(rippleBounds);
}
dirtyBounds.union(drawingBounds);
@@ -539,34 +433,30 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
@Override
public ConstantState getConstantState() {
- // TODO: Can we just rely on super.getConstantState()?
return mState;
}
- static class TouchFeedbackState extends WrapperState {
- int[] mThemeAttrs;
- ConstantState mMaskState;
+ static class TouchFeedbackState extends LayerState {
+ int[] mTouchThemeAttrs;
ColorStateList mTint;
Mode mTintMode;
boolean mPinned;
- boolean mProjected;
- public TouchFeedbackState(TouchFeedbackState orig) {
- super(orig);
+ public TouchFeedbackState(
+ TouchFeedbackState orig, TouchFeedbackDrawable owner, Resources res) {
+ super(orig, owner, res);
if (orig != null) {
- mThemeAttrs = orig.mThemeAttrs;
+ mTouchThemeAttrs = orig.mTouchThemeAttrs;
mTint = orig.mTint;
mTintMode = orig.mTintMode;
- mMaskState = orig.mMaskState;
mPinned = orig.mPinned;
- mProjected = orig.mProjected;
}
}
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null;
+ return mTouchThemeAttrs != null || super.canApplyTheme();
}
@Override
@@ -586,13 +476,33 @@ public class TouchFeedbackDrawable extends DrawableWrapper {
}
private TouchFeedbackDrawable(TouchFeedbackState state, Resources res, Theme theme) {
- if (theme != null && state.canApplyTheme()) {
- mState = new TouchFeedbackState(state);
- applyTheme(theme);
+ boolean needsTheme = false;
+
+ final TouchFeedbackState ns;
+ if (theme != null && state != null && state.canApplyTheme()) {
+ ns = new TouchFeedbackState(state, this, res);
+ needsTheme = true;
+ } else if (state == null) {
+ ns = new TouchFeedbackState(null, this, res);
} else {
- mState = state;
+ ns = state;
+ }
+
+ if (res != null) {
+ mDensity = res.getDisplayMetrics().density;
+ }
+
+ mState = ns;
+ mLayerState = ns;
+
+ if (ns.mNum > 0) {
+ ensurePadding();
+ }
+
+ if (needsTheme) {
+ applyTheme(theme);
}
- setConstantState(state, res);
+ setPaddingMode(PADDING_MODE_STACK);
}
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
new file mode 100644
index 0000000..f3dd2fc
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -0,0 +1,1955 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.graphics.drawable;
+
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.Resources.Theme;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.location.Address;
+import android.net.ParseException;
+import android.sax.StartElementListener;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+/**
+ * This lets you create a drawable based on an XML vector graphic
+ * It can be defined in an XML file with the <code>&lt;vector></code> element.
+ * <p/>
+ * The vector drawable has 6 elements:
+ * <p/>
+ * <dl>
+ * <dt><code>&lt;vector></code></dt><dd>
+ * The attribute <code>android:trigger</code> which defines a state change that
+ * will drive the animation </dd>
+ * <dt><code>&lt;size></code></dt>
+ * <dd>Used to defined the intrinsic Width Height size of the drawable using
+ * <code>android:width</code> and <code>android:height</code> </dd>
+ * <dt><code>&lt;viewport></code></dt>
+ * <dd>Used to defined the size of the virtual canvas the paths are drawn on.
+ * The size is defined using the attributes <code>android:viewportHeight
+ * </code> <code>android:viewportWidth</code></dd>
+ * <dt><code>&lt;group></code></dt>
+ * <dd>Defines a "key frame" in the animation if there is only one group the
+ * drawable is static 2D image that has no animation.</dd>
+ * <dt><code>&lt;path></code></dt>
+ * <dd>Defines paths to be drawn. The path elements must be within a group
+ * <dl>
+ * <dt><code>android:name</code>
+ * <dd>Defines the name of the path.</dd></dt>
+ * <dt><code>android:pathData</code>
+ * <dd>Defines path string.</dd></dt>
+ * <dt><code>android:fill</code>
+ * <dd>Defines the color to fill the path (none if not present).</dd></dt>
+ * <dt><code>android:stroke</code>
+ * <dd>Defines the color to draw the path outline (none if not present).</dd></dt>
+ * <dt><code>android:strokeWidth</code>
+ * <dd>The width a path stroke</dd></dt>
+ * <dt><code>android:strokeOpacity</code>
+ * <dd>The opacity of a path stroke</dd></dt>
+ * <dt><code>android:rotation</code>
+ * <dd>The amount to rotation the path stroke.</dd></dt>
+ * <dt><code>android:pivotX</code>
+ * <dd>The X coordinate of the center of rotation of a path</dd></dt>
+ * <dt><code>android:pivotY</code>
+ * <dd>The Y coordinate of the center of rotation of a path</dd></dt>
+ * <dt><code>android:fillOpacity</code>
+ * <dd>The opacity to fill the path with</dd></dt>
+ * <dt><code>android:trimPathStart</code>
+ * <dd>The fraction of the path to trim from the start from 0 to 1</dd></dt>
+ * <dt><code>android:trimPathEnd</code>
+ * <dd>The fraction of the path to trim from the end from 0 to 1</dd></dt>
+ * <dt><code>android:trimPathOffset</code>
+ * <dd>Shift trim region (allows showed region to include the start and end) from 0 to 1</dd></dt>
+ * <dt><code>android:clipToPath</code>
+ * <dd>Path will set the clip path</dd></dt>
+ * <dt><code>android:strokeLineCap</code>
+ * <dd>Sets the linecap for a stroked path: butt, round, square</dd></dt>
+ * <dt><code>android:strokeLineJoin</code>
+ * <dd>Sets the lineJoin for a stroked path: miter,round,bevel</dd></dt>
+ * <dt><code>android:strokeMiterLimit</code>
+ * <dd>Sets the Miter limit for a stroked path</dd></dt>
+ * <dt><code>android:state_pressed</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_focused</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_selected</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_window_focused</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_enabled</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_activated</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_accelerated</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_hovered</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_checked</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_checkable</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * </dl>
+ * </dd>
+ * <dt><code>&lt;animation></code></dt>
+ * <dd>Used to customize the transition between two paths
+ * <dl>
+ * <dt><code>android:sequence</code>
+ * <dd>Configures this animation sequence between the named paths.</dd></dt>
+ * <dt><code>android:limitTo</code>
+ * <dd>Limits an animation to only interpolate the selected variable
+ * unlimited, path, rotation, trimPathStart, trimPathEnd, trimPathOffset</dd></dt>
+ * <dt><code>android:repeatCount</code>
+ * <dd>Number of times to loop this aspect of the animation</dd></dt>
+ * <dt><code>android:durations</code>
+ * <dd>The duration of each step in the animation in milliseconds
+ * Must contain the number of named paths - 1</dd></dt>
+ * <dt><code>android:startDelay</code>
+ * <dd></dd></dt>
+ * <dt><code>android:repeatStyle</code>
+ * <dd>when repeating how does it repeat back and forth or a to b: forward, inAndOut</dd></dt>
+ * <dt><code>android:animate</code>
+ * <dd>linear, accelerate, decelerate, easing</dd></dt>
+ * </dl>
+ * </dd>
+ */
+public class VectorDrawable extends Drawable {
+ private static final String LOGTAG = "VectorDrawable";
+ public static final int INFINITE = ValueAnimator.INFINITE;
+ private static final String SHAPE_SIZE = "size";
+ private static final String SHAPE_VIEWPORT = "viewport";
+ private static final String SHAPE_GROUP = "group";
+ private static final String SHAPE_PATH = "path";
+ private static final String SHAPE_TRANSITION = "transition";
+ private static final String SHAPE_ANIMATION = "animation";
+ private static final String SHAPE_VECTOR = "vector";
+
+ private static final int LINECAP_BUTT = 0;
+ private static final int LINECAP_ROUND = 1;
+ private static final int LINECAP_SQUARE = 2;
+ private static final int LINEJOIN_MITER = 0;
+ private static final int LINEJOIN_ROUND = 1;
+ private static final int LINEJOIN_BEVEL = 2;
+ private static final int DEFAULT_DURATION = 1000;
+ private static final long DEFAULT_INFINITE_DURATION = 60 * 60 * 1000;
+ private VectorDrawableState mVectorState;
+ private int mAlpha = 0xFF;
+
+ public VectorDrawable() {
+ mVectorState = new VectorDrawableState();
+ mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+ setDuration(DEFAULT_DURATION);
+ }
+
+ private VectorDrawable(VectorDrawableState state) {
+ mVectorState = new VectorDrawableState(state);
+ mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+ long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
+ if (duration == -1) { // if it set to infinite set to 1 hour
+ duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
+ mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
+ mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
+ }
+ setDuration(duration);
+ }
+
+ final static class VectorDrawableState extends ConstantState {
+ int mChangingConfigurations;
+ ValueAnimator mBasicAnimator;
+ VAnimatedPath mVAnimatedPath = new VAnimatedPath();
+ Rect mPadding;
+ int mIntrinsicHeight;
+ int mIntrinsicWidth;
+
+ public VectorDrawableState(){
+ }
+
+ public VectorDrawableState(VectorDrawableState copy){
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
+ mPadding = new Rect(copy.mPadding);
+ mIntrinsicHeight = copy.mIntrinsicHeight;
+ mIntrinsicWidth = copy.mIntrinsicWidth;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new VectorDrawable(this);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return mChangingConfigurations;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see android.graphics.drawable.Drawable#getConstantState()
+ */
+ @Override
+ public ConstantState getConstantState() {
+ return mVectorState;
+ }
+
+ /**
+ * start the animation
+ */
+ public void start() {
+ mVectorState.mBasicAnimator.start();
+ }
+
+ /**
+ * Stop the animation.
+ */
+ public void stop() {
+ mVectorState.mBasicAnimator.end();
+ }
+
+ /**
+ * Get the current time point in the animation
+ *
+ * @return the current point on the animation
+ */
+ public float geAnimationFraction() {
+ return mVectorState.mVAnimatedPath.getValue();
+ }
+
+ /**
+ * set the time point in the animation
+ *
+ * @param value the point along the animation typically between 0 and 1
+ */
+ public void setAnimationFraction(float value) {
+ mVectorState.mVAnimatedPath.setAnimationFraction(value);
+ invalidateSelf();
+ }
+
+ /**
+ * set the amount of time the animation will take
+ *
+ * @param duration amount of time in milliseconds
+ */
+ public void setDuration(long duration) {
+ mVectorState.mBasicAnimator.setDuration(duration);
+ }
+
+ /**
+ * Defines what this animation should do when it reaches the end. This setting is applied only
+ * when the repeat count is either greater than 0 or {@link #INFINITE}.
+ */
+ public void setRepeatMode(int mode) {
+ mVectorState.mBasicAnimator.setRepeatMode(mode);
+ }
+
+ /**
+ * Sets animation to repeat
+ *
+ * @param repeat True if this drawable repeats its animation
+ */
+ public void setRepeatCount(int repeat) {
+ mVectorState.mBasicAnimator.setRepeatCount(repeat);
+ }
+
+ /**
+ * @return True if this drawable repeats its animation
+ */
+ public int getRepeatCount() {
+ return mVectorState.mBasicAnimator.getRepeatCount();
+ }
+
+ @Override
+ public boolean isStateful() {
+ return true;
+ }
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ mVectorState.mVAnimatedPath.setState(state);
+ int direction = mVectorState.mVAnimatedPath.getTrigger(state);
+ if (direction>0) {
+ animateForward();
+ } else if (direction<0) {
+ animateBackward();
+ }
+ super.onStateChange(state);
+ invalidateSelf();
+ return true;
+ }
+
+ private void animateForward(){
+ if (!mVectorState.mBasicAnimator.isStarted()) {
+ mVectorState.mBasicAnimator.setFloatValues(0,1);
+ start();
+ }
+ }
+
+ private void animateBackward(){
+ if (!mVectorState.mBasicAnimator.isStarted()) {
+ mVectorState.mBasicAnimator.setFloatValues(.99f,0);
+ start();
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ mVectorState.mVAnimatedPath.draw(canvas);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // TODO correct handling of transparent
+ if (mAlpha != alpha) {
+ mAlpha = alpha;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Not implemented yet
+ * @hide
+ */
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ // TODO: support color filter
+ }
+
+ /**
+ * Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
+ * value of TRANSLUCENT.
+ */
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ /**
+ * Sets padding for this shape, defined by a Rect object. Define the padding in the Rect object
+ * as: left, top, right, bottom.
+ */
+ public void setPadding(Rect padding) {
+ setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ }
+
+ /**
+ * Sets padding for the shape.
+ *
+ * @param left padding for the left side (in pixels)
+ * @param top padding for the top (in pixels)
+ * @param right padding for the right side (in pixels)
+ * @param bottom padding for the bottom (in pixels)
+ */
+ public void setPadding(int left, int top, int right, int bottom) {
+ if ((left | top | right | bottom) == 0) {
+ mVectorState.mPadding = null;
+ } else {
+ if (mVectorState.mPadding == null) {
+ mVectorState.mPadding = new Rect();
+ }
+ mVectorState.mPadding.set(left, top, right, bottom);
+ }
+ invalidateSelf();
+ }
+
+ /**
+ * Sets the intrinsic (default) width for this shape.
+ *
+ * @param width the intrinsic width (in pixels)
+ */
+ public void setIntrinsicWidth(int width) {
+ if (mVectorState.mIntrinsicWidth != width) {
+ mVectorState.mIntrinsicWidth = width;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Sets the intrinsic (default) height for this shape.
+ *
+ * @param height the intrinsic height (in pixels)
+ */
+ public void setIntrinsicHeight(int height) {
+ if (mVectorState.mIntrinsicHeight != height) {
+ mVectorState.mIntrinsicHeight = height;
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mVectorState.mIntrinsicWidth;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mVectorState.mIntrinsicHeight;
+ }
+
+ @Override
+ public boolean getPadding(Rect padding) {
+ if (mVectorState.mPadding != null) {
+ padding.set(mVectorState.mPadding);
+ return true;
+ } else {
+ return super.getPadding(padding);
+ }
+ }
+
+ /** @hide */
+ public static VectorDrawable create(Resources resources, int rid) {
+ try {
+ VectorDrawable drawable = new VectorDrawable();
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ XmlPullParser xpp = resources.getXml(rid);
+ AttributeSet attrs = Xml.asAttributeSet(xpp);
+ drawable.inflate(resources, xpp, attrs);
+ drawable.setAnimationFraction(0);
+ return drawable;
+ } catch (XmlPullParserException e) {
+ Log.e(LOGTAG, "parser error", e);
+ } catch (IOException e) {
+ Log.e(LOGTAG, "parser error", e);
+ }
+ return null;
+ }
+
+ @Override
+ public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
+ throws XmlPullParserException, IOException {
+ setAnimatedPath(inflateInternal(res, parser, attrs));
+ }
+
+ private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs)
+ throws XmlPullParserException, IOException {
+ boolean noSizeTag = true;
+ boolean noViewportTag = true;
+ boolean noGroupTag = true;
+ boolean noPathTag = true;
+ final VAnimatedPath animatedPath = new VAnimatedPath();
+ VectorDrawable.VGroup currentGroup = null;
+
+ int eventType = parser.getEventType();
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ String tagName = parser.getName();
+ if (SHAPE_PATH.equals(tagName)) {
+ VectorDrawable.VPath p = new VPath(res, attrs);
+ currentGroup.add(p);
+ noPathTag = false;
+ } else if (SHAPE_ANIMATION.equals(tagName)) {
+ VectorDrawable.VAnimation anim =
+ new VAnimation(res, attrs, animatedPath.mGroupList);
+ animatedPath.addAnimation(anim);
+ } else if (SHAPE_SIZE.equals(tagName)) {
+ animatedPath.parseSize(res, attrs);
+ noSizeTag = false;
+ } else if (SHAPE_VIEWPORT.equals(tagName)) {
+ animatedPath.parseViewport(res, attrs);
+ noViewportTag = false;
+ } else if (SHAPE_GROUP.equals(tagName)) {
+ currentGroup = new VectorDrawable.VGroup();
+ animatedPath.mGroupList.add(currentGroup);
+ noGroupTag = false;
+ } else if (SHAPE_VECTOR.equals(tagName)) {
+ TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable);
+ animatedPath.setTrigger(a.getInteger(R.styleable.VectorDrawable_trigger, 0));
+ a.recycle();
+ }
+ }
+ eventType = parser.next();
+ }
+ if (noSizeTag || noViewportTag || noGroupTag || noPathTag) {
+ StringBuffer tag = new StringBuffer();
+ if (noSizeTag) {
+ tag.append("size");
+ }
+ if (noViewportTag){
+ if (tag.length()>0) {
+ tag.append(" & ");
+ }
+ tag.append("size");
+ }
+ if (noGroupTag){
+ if (tag.length()>0) {
+ tag.append(" & ");
+ }
+ tag.append("group");
+ }
+ if (noPathTag){
+ if (tag.length()>0) {
+ tag.append(" or ");
+ }
+ tag.append("path");
+ }
+ throw new XmlPullParserException("no "+tag+" defined");
+ }
+ // post parse cleanup
+ animatedPath.parseFinish();
+ return animatedPath;
+ }
+
+ private void setAnimatedPath(VAnimatedPath animatedPath) {
+ mVectorState.mVAnimatedPath = animatedPath;
+ setIntrinsicWidth((int) mVectorState.mVAnimatedPath.mBaseWidth);
+ setIntrinsicHeight((int) mVectorState.mVAnimatedPath.mBaseHeight);
+ long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
+ if (duration == -1) { // if it set to infinite set to 1 hour
+ duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
+ mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
+ mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
+ }
+ setDuration(duration);
+
+ setAnimationFraction(0);
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ boolean changed = super.setVisible(visible, restart);
+ if (visible) {
+ if (changed || restart) {
+ setAnimationFraction(0);
+ }
+ } else {
+ stop();
+ }
+ return changed;
+ }
+
+ private static class VAnimatedPath {
+ private static final String LOGTAG = "VAnimatedPath";
+
+ private ArrayList<VAnimation> mCurrentAnimList = null;
+ private VPath[] mCurrentPaths;
+ private float mAnimationValue = 0; // value goes from 0 to 1
+ private Paint mStrokePaint = null;
+ private Paint mFillPaint = null;
+ private PathMeasure mPathMeasure;
+ private Path mPath = new Path();
+ private Path mRenderPath = new Path();
+ private Matrix mMatrix = new Matrix();
+ private long mTotalDuration;
+ private int[] mCurrentState = new int[0];
+ private int mTrigger;
+ private boolean mTriggerState;
+ ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
+ float mBaseWidth = 1;
+ float mBaseHeight = 1;
+ float mViewportWidth;
+ float mViewportHeight;
+
+ public VAnimatedPath() {
+ setup();
+ }
+ public VAnimatedPath(VAnimatedPath copy) {
+ setup();
+ mCurrentAnimList = new ArrayList<VAnimation>(copy.mCurrentAnimList);
+ mGroupList = new ArrayList<VGroup>(copy.mGroupList);
+ if (copy.mCurrentPaths != null) {
+ mCurrentPaths = new VPath[copy.mCurrentPaths.length];
+ for (int i = 0; i < mCurrentPaths.length; i++) {
+ mCurrentPaths[i] = new VPath(copy.mCurrentPaths[i]);
+ }
+ }
+ mAnimationValue = copy.mAnimationValue; // time goes from 0 to 1
+
+ mBaseWidth = copy.mBaseWidth;
+ mBaseHeight = copy.mBaseHeight;
+ mViewportWidth = copy.mViewportHeight;
+ mViewportHeight = copy.mViewportHeight;
+ mTotalDuration = copy.mTotalDuration;
+ mTrigger = copy.mTrigger;
+ mCurrentState = new int[0];
+ }
+
+ public void setTrigger(int trigger){
+ int []lut = { 0,
+ R.attr.state_pressed,
+ R.attr.state_focused,
+ R.attr.state_hovered,
+ R.attr.state_selected,
+ R.attr.state_checkable,
+ R.attr.state_checked,
+ R.attr.state_activated,
+ R.attr.state_focused
+ };
+ mTrigger = lut[trigger];
+ }
+
+ private void setup(){
+ mStrokePaint = new Paint();
+ mStrokePaint.setStyle(Paint.Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ mFillPaint = new Paint();
+ mFillPaint.setStyle(Paint.Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+
+ public long getTotalAnimationDuration() {
+ mTotalDuration = 0;
+ int size = mCurrentAnimList.size();
+ for (int i = 0; i < size; i++) {
+ VAnimation vAnimation = mCurrentAnimList.get(i);
+ long t = vAnimation.getTotalDuration();
+ if (t == -1) {
+ mTotalDuration = -1;
+ return -1;
+ }
+ mTotalDuration = Math.max(mTotalDuration, t);
+ }
+
+ return mTotalDuration;
+ }
+
+ public float getValue() {
+ return mAnimationValue;
+ }
+
+ /**
+ * @param value the point along the animations to show typically between 0.0f and 1.0f
+ * @return true if you need to keep repeating
+ */
+ public boolean setAnimationFraction(float value) {
+ int len = mCurrentPaths.length;
+ getTotalAnimationDuration();
+ long animationTime = (long) (value * mTotalDuration);
+
+ for (int i = 0; i < len; i++) {
+ VPath path = mCurrentPaths[i];
+ animationTime =
+ (long) ((mTotalDuration == -1) ? value * 1000 : mTotalDuration * value);
+ int size = mCurrentAnimList.size();
+ for (int j = 0; j < size; j++) {
+ VAnimation vAnimation = mCurrentAnimList.get(j);
+ if (vAnimation.doesAdjustPath(path)) {
+ mCurrentPaths[i] = vAnimation.getPathAtTime(animationTime, path);
+ }
+ }
+ }
+ this.mAnimationValue = value;
+ if (mTotalDuration == -1) {
+ return true;
+ } else {
+ return animationTime < mTotalDuration;
+ }
+ }
+
+ public void draw(Canvas canvas) {
+ int w = canvas.getWidth();
+ int h = canvas.getHeight();
+ float scale = w / mViewportWidth;
+ scale = Math.min(h / mViewportHeight, scale);
+
+ if (mCurrentPaths == null) {
+ Log.e(LOGTAG,"mCurrentPaths == null");
+ return;
+ }
+
+ for (int i = 0; i < mCurrentPaths.length; i++) {
+ if (mCurrentPaths[i] != null && mCurrentPaths[i].isVisible(mCurrentState)) {
+ drawPath(mCurrentPaths[i], canvas, w, h);
+ }
+ }
+ }
+
+ private void drawPath(VPath vPath, Canvas canvas, int w, int h) {
+ float scale = w / mViewportWidth;
+ scale = Math.min(h / mViewportHeight, scale);
+
+ vPath.toPath(mPath);
+ Path path = mPath;
+
+ if (vPath.mTrimPathStart != 0.0f || vPath.mTrimPathEnd != 1.0f) {
+ float start = (vPath.mTrimPathStart + vPath.mTrimPathOffset) % 1.0f;
+ float end = (vPath.mTrimPathEnd + vPath.mTrimPathOffset) % 1.0f;
+
+ if (mPathMeasure == null) {
+ mPathMeasure = new PathMeasure();
+ }
+ mPathMeasure.setPath(mPath, false);
+
+ float len = mPathMeasure.getLength();
+ start = start * len;
+ end = end * len;
+ path.reset();
+ if (start > end) {
+ mPathMeasure.getSegment(start, len, path, true);
+ mPathMeasure.getSegment(0f, end, path, true);
+ } else {
+ mPathMeasure.getSegment(start, end, path, true);
+ }
+ path.rLineTo(0, 0); // fix bug in measure
+ }
+
+ mRenderPath.reset();
+ mMatrix.reset();
+
+ mMatrix.postRotate(vPath.mRotate, vPath.mPivotX, vPath.mPivotY);
+ mMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
+ mMatrix.postTranslate(w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
+
+ mRenderPath.addPath(path, mMatrix);
+
+ if (vPath.mClip) {
+ canvas.clipPath(mRenderPath, Region.Op.REPLACE);
+ }
+ if (vPath.mFillColor != 0) {
+ mFillPaint.setColor(vPath.mFillColor);
+ int alpha = 0xFF & (vPath.mFillColor >> 24);
+ mFillPaint.setAlpha(alpha);
+ canvas.drawPath(mRenderPath, mFillPaint);
+ }
+ if (vPath.mStrokeColor != 0) {
+ if (vPath.mStrokelineJoin != null) {
+ mStrokePaint.setStrokeJoin(vPath.mStrokelineJoin);
+ }
+ if (vPath.mStrokelineCap != null) {
+ mStrokePaint.setStrokeCap(vPath.mStrokelineCap);
+ }
+ mStrokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
+ mStrokePaint.setColor(vPath.mStrokeColor);
+ mStrokePaint.setAlpha(0xFF & (vPath.mStrokeColor >> 24));
+ mStrokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
+ canvas.drawPath(mRenderPath, mStrokePaint);
+ }
+ }
+
+ /**
+ * Ensure there is at least one animation for every path in group (linking them by names)
+ * Build the "current" path based on the first group
+ * TODO: improve memory use & performance or move to C++
+ */
+ public void parseFinish() {
+ HashMap<String, VAnimation> newAnimations = new HashMap<String, VAnimation>();
+ for (VGroup group : mGroupList) {
+ for (VPath vPath : group.getPaths()) {
+ if (!vPath.mAnimated) {
+ VAnimation ap = null;
+
+ if (!newAnimations.containsKey(vPath.getID())) {
+ newAnimations.put(vPath.getID(), ap = new VAnimation());
+ } else {
+ ap = newAnimations.get(vPath.getID());
+ }
+ ap.addPath(vPath);
+ vPath.mAnimated = true;
+ }
+ }
+ }
+ if (mCurrentAnimList == null) {
+ mCurrentAnimList = new ArrayList<VectorDrawable.VAnimation>();
+ }
+ mCurrentAnimList.addAll(newAnimations.values());
+ Collection<VPath> paths = mGroupList.get(0).getPaths();
+ mCurrentPaths = paths.toArray(new VPath[paths.size()]);
+ for (int i = 0; i < mCurrentPaths.length; i++) {
+ mCurrentPaths[i] = new VPath(mCurrentPaths[i]);
+ }
+ }
+
+ public void setState(int[] state) {
+ mCurrentState = Arrays.copyOf(state, state.length);
+ }
+
+ int getTrigger(int []state){
+ if (mTrigger == 0) return 0;
+ for (int i = 0; i < state.length; i++) {
+ if (state[i] == mTrigger){
+ if (mTriggerState)
+ return 0;
+ mTriggerState = true;
+ return 1;
+ }
+ }
+ if (mTriggerState) {
+ mTriggerState = false;
+ return -1;
+ }
+ return 0;
+ }
+
+ public void addAnimation(VAnimation anim) {
+ if (mCurrentAnimList == null) {
+ mCurrentAnimList = new ArrayList<VectorDrawable.VAnimation>();
+ }
+ mCurrentAnimList.add(anim);
+ }
+
+ private void parseViewport(Resources r, AttributeSet attrs)
+ throws XmlPullParserException {
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
+ mViewportWidth = a.getFloat(R.styleable.VectorDrawableViewport_viewportWidth, 0);
+ mViewportHeight = a.getFloat(R.styleable.VectorDrawableViewport_viewportHeight, 0);
+ if (mViewportWidth == 0 || mViewportHeight == 0) {
+ throw new XmlPullParserException(a.getPositionDescription()+
+ "<viewport> tag requires viewportWidth & viewportHeight to be set");
+ }
+ a.recycle();
+ }
+
+ private void parseSize(Resources r, AttributeSet attrs)
+ throws XmlPullParserException {
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
+ mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, 0);
+ mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, 0);
+ if (mBaseWidth == 0 || mBaseHeight == 0) {
+ throw new XmlPullParserException(a.getPositionDescription()+
+ "<size> tag requires width & height to be set");
+ }
+ a.recycle();
+ }
+ }
+
+ private static class VAnimation {
+ private static final String LOGTAG = "VAnimation";
+ private VPath[] mPaths = new VPath[0];
+
+ public enum Style {
+ INTERPOLATE, CROSSFADE, WIPE
+ }
+ Interpolator mAnimInterpolator = new AccelerateDecelerateInterpolator();
+ private Style mStyle;
+ private int mLimitProperty = 0;
+ private long[] mDuration = {DEFAULT_DURATION};
+ private long mStartOffset;
+ private long mRepeat = 1;
+ private HashSet<String>mSeqMap = new HashSet<String>();
+ private long mWipeDirection;
+ private int mMode = 0; // forward = 0 inAndOut = 1;
+ private int mInterpolatorType;
+ private String mId;
+ private final static int DIRECTION_FORWARD = 0;
+ private final static int DIRECTION_IN_AND_OUT = 1;
+
+ public VAnimation() {
+ }
+
+ public boolean doesAdjustPath(VPath path) {
+ return mSeqMap.contains(path.getID());
+ }
+
+ public VAnimation(Resources r, AttributeSet attrs, ArrayList<VGroup> groups)
+ throws XmlPullParserException {
+ String value;
+ String[] sp;
+ int name;
+
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableAnimation);
+
+ value = a.getString(R.styleable.VectorDrawableAnimation_sequence);
+ if (value != null) {
+ sp = value.split(",");
+ VectorDrawable.VPath[] paths = new VectorDrawable.VPath[sp.length];
+
+ for (int j = 0; j < sp.length; j++) {
+ mSeqMap.add(sp[j].trim());
+ VectorDrawable.VPath path = groups.get(j).get(sp[j]);
+ path.mAnimated = true;
+ paths[j] = path;
+ }
+ setPaths(paths);
+ }
+
+ setLimitProperty(a.getInt(R.styleable.VectorDrawableAnimation_limitTo, 0));
+
+ name = R.styleable.VectorDrawableAnimation_durations;
+ value = a.getString(name);
+ if (value != null) {
+ long totalDuration = 0;
+ sp = value.split(",");
+ long[] dur = new long[sp.length];
+ for (int j = 0; j < dur.length; j++) {
+ dur[j] = Long.parseLong(sp[j]);
+ totalDuration += dur[j];
+ }
+ if (totalDuration == 0){
+ throw new XmlPullParserException(a.getPositionDescription()+
+ "total duration must not be zero");
+ }
+ setDuration(dur);
+ }
+
+ setRepeat(a.getInt(R.styleable.VectorDrawableAnimation_repeatCount, 1));
+
+ setStartOffset(a.getInt(R.styleable.VectorDrawableAnimation_startDelay, 0));
+
+ setMode(a.getInt(R.styleable.VectorDrawableAnimation_repeatStyle, 0));
+
+ fixMissingParameters();
+ a.recycle();
+ }
+
+ public String getId() {
+ if (mId == null) {
+ mId = mPaths[0].getID();
+ for (int i = 1; i < mPaths.length; i++) {
+ mId += mPaths[i].getID();
+ }
+ }
+ return mId;
+ }
+
+ public String getPathName() {
+ return mPaths[0].getID();
+ }
+
+ public Style getStyle() {
+ return mStyle;
+ }
+
+ public void setStyle(Style style) {
+ this.mStyle = style;
+ }
+
+ public int getLimitProperty() {
+ return mLimitProperty;
+ }
+
+ public void setLimitProperty(int limitProperty) {
+ this.mLimitProperty = limitProperty;
+ }
+
+ public long[] getDuration() {
+ return mDuration;
+ }
+
+ public void setDuration(long[] duration) {
+ this.mDuration = duration;
+ }
+
+ public long getRepeat() {
+ return mRepeat;
+ }
+
+ public void setRepeat(long repeat) {
+ this.mRepeat = repeat;
+ }
+
+ public long getStartOffset() {
+ return mStartOffset;
+ }
+
+ public void setStartOffset(long startOffset) {
+ this.mStartOffset = startOffset;
+ }
+
+ public long getWipeDirection() {
+ return mWipeDirection;
+ }
+
+ public void setWipeDirection(long wipeDirection) {
+ this.mWipeDirection = wipeDirection;
+ }
+
+ public int getMode() {
+ return mMode;
+ }
+
+ public void setMode(int mode) {
+ this.mMode = mode;
+ }
+
+ public int getInterpolator() {
+ return mInterpolatorType;
+ }
+
+ public void setInterpolator(int interpolator) {
+ this.mInterpolatorType = interpolator;
+ }
+
+ /**
+ * compute the total time in milliseconds
+ *
+ * @return the total time in milliseconds the animation will take
+ */
+ public long getTotalDuration() {
+ long total = mStartOffset;
+ if (getRepeat() == -1) {
+ return -1;
+ }
+ for (int i = 0; i < mDuration.length; i++) {
+ if (mRepeat > 1) {
+ total += mDuration[i] * mRepeat;
+ } else {
+ total += mDuration[i];
+ }
+ }
+ return total;
+ }
+
+ public void setPaths(VPath[] paths) {
+ this.mPaths = paths;
+ }
+
+ public void addPath(VPath path) {
+ mPaths = Arrays.copyOf(mPaths, mPaths.length + 1);
+ mPaths[mPaths.length - 1] = path;
+ }
+
+ public boolean containsPath(String pathid) {
+ for (int i = 0; i < mPaths.length; i++) {
+ if (mPaths[i].getID().equals(pathid)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void interpolate(VPath p1, VPath p2, float time, VPath dest) {
+ dest.interpolate(time, p1, p2, dest, mLimitProperty);
+ }
+
+ public VPath getPathAtTime(long milliseconds, VPath dest) {
+ if (mPaths.length == 1) {
+ dest.copyFrom(mPaths[0]);
+ return dest;
+ }
+ long point = milliseconds - mStartOffset;
+ if (point < 0) {
+ point = 0;
+ }
+ float time = 0;
+ long sum = mDuration[0];
+ for (int i = 1; i < mDuration.length; i++) {
+ sum += mDuration[i];
+ }
+
+ if (mRepeat > 1) {
+ time = point / (float) (sum * mRepeat);
+ time = mAnimInterpolator.getInterpolation(time);
+
+ if (mMode == DIRECTION_IN_AND_OUT) {
+ point = ((long) (time * sum * 2 * mRepeat)) % (sum * 2);
+ if (point > sum) {
+ point = sum * 2 - point;
+ }
+ } else {
+ point = ((long) (time * sum * mRepeat)) % sum;
+ }
+ } else if (mRepeat == 1) {
+ time = point / (float) (sum * mRepeat);
+ time = mAnimInterpolator.getInterpolation(time);
+ if (mMode == DIRECTION_IN_AND_OUT) {
+ point = ((long) (time * sum * 2 * mRepeat));
+ if (point > sum) {
+ point = sum * 2 - point;
+ }
+ } else {
+ point = Math.min(((long) (time * sum * mRepeat)), sum);
+ }
+
+ } else { // repeat = -1
+ if (mMode == DIRECTION_IN_AND_OUT) {
+ point = point % (sum * 2);
+ if (point > sum) {
+ point = sum * 2 - point;
+ }
+ time = point / (float) sum;
+ } else {
+ point = point % sum;
+ time = point / (float) sum;
+ }
+ }
+
+ int transition = 0;
+ while (point > mDuration[transition]) {
+ point -= mDuration[transition++];
+ }
+ if (mPaths.length > (transition + 1)) {
+ if (mPaths[transition].getID() != dest.getID()) {
+ dest.copyFrom(mPaths[transition]);
+ }
+ interpolate(mPaths[transition], mPaths[transition + 1],
+ point / (float) mDuration[transition], dest);
+ } else {
+ interpolate(mPaths[transition], mPaths[transition], 0, dest);
+ }
+ return dest;
+ }
+
+ void fixMissingParameters() {
+ // fix missing points
+ float rotation = Float.NaN;
+ float rotationY = Float.NaN;
+ float rotationX = Float.NaN;
+ for (int i = 0; i < mPaths.length; i++) {
+ if (mPaths[i].mPivotX > 0) {
+ rotationX = mPaths[i].mPivotX;
+ }
+ if (mPaths[i].mPivotY > 0) {
+ rotationY = mPaths[i].mPivotY;
+ }
+ if (mPaths[i].mRotate > 0) {
+ rotation = mPaths[i].mRotate;
+ }
+ }
+ if (rotation > 0) {
+ for (int i = 0; i < mPaths.length; i++) {
+ if (mPaths[i].mPivotX == 0) {
+ mPaths[i].mPivotX = rotationX;
+ }
+ if (mPaths[i].mPivotY == 0) {
+ mPaths[i].mPivotY = rotationY;
+ }
+ }
+ }
+ }
+ }
+
+ private static class VGroup {
+ private HashMap<String, VPath> mVGPathMap = new HashMap<String, VPath>();
+ private ArrayList<VPath> mVGList = new ArrayList<VPath>();
+
+ public void add(VPath path) {
+ String id = path.getID();
+ mVGPathMap.put(id, path);
+ mVGList.add(path);
+ }
+
+ public VPath get(String name) {
+ return mVGPathMap.get(name);
+ }
+
+ /**
+ * Must return in order of adding
+ * @return ordered list of paths
+ */
+ public Collection<VPath> getPaths() {
+ return mVGList;
+ }
+
+ public int size() {
+ return mVGPathMap.size();
+ }
+ }
+
+ private static class VPath {
+ private static final int LIMIT_ALL = 0;
+ private static final int LIMIT_PATH = 1;
+ private static final int LIMIT_ROTATE = 2;
+ private static final int LIMIT_TRIM_PATH_START = 3;
+ private static final int LIMIT_TRIM_PATH_OFFSET = 5;
+ private static final int LIMIT_TRIM_PATH_END = 4;
+ private static final int STATE_UNDEFINED=0;
+ private static final int STATE_TRUE=1;
+ private static final int STATE_FALSE=2;
+ private static final int MAX_STATES = 10;
+ private VNode[] mNode = null;
+ private String mId;
+ int mStrokeColor = 0;
+ float mStrokeWidth = 0;
+ float mStrokeOpacity = Float.NaN;
+ int mFillColor = 0;
+ int mFillRule;
+ float mFillOpacity = Float.NaN;
+ float mRotate = 0;
+ float mPivotX = 0;
+ float mPivotY = 0;
+ float mTrimPathStart = 0;
+ float mTrimPathEnd = 1;
+ float mTrimPathOffset = 0;
+ boolean mAnimated = false;
+ boolean mClip = false;
+ public Paint.Cap mStrokelineCap = null;
+ public Paint.Join mStrokelineJoin = null;
+ float mStrokeMiterlimit = 4;
+ private int[] mCheckState = new int[MAX_STATES];
+ private boolean[] mCheckValue = new boolean[MAX_STATES];
+ private int mNumberOfStates = 0;
+ private int mNumberOfTrue = 0;
+
+ public void addStateFilter(int state, boolean condition) {
+ int k = 0;
+ while (k < mNumberOfStates) {
+ if (mCheckState[mNumberOfStates] == state)
+ break;
+ k++;
+ }
+ mCheckState[k] = state;
+ mCheckValue[k] = condition;
+ if (k==mNumberOfStates){
+ mNumberOfStates++;
+ }
+ if (condition) {
+ mNumberOfTrue++;
+ }
+ }
+
+ int getState(int state){
+ for (int i = 0; i < mNumberOfStates; i++) {
+ if (mCheckState[mNumberOfStates] == state){
+ return (mCheckValue[i])?STATE_TRUE:STATE_FALSE;
+ }
+ }
+ return STATE_UNDEFINED;
+ }
+ /**
+ * @return the name of the path
+ */
+ public String getName() {
+ return mId;
+ }
+
+ public void toPath(Path path) {
+ path.reset();
+ if (mNode != null) {
+ VNode.createPath(mNode, path);
+ }
+ }
+
+ public VPath() {
+ mId = this.toString(); // to ensure paths have unique names
+ }
+
+ public VPath(VPath p) {
+ copyFrom(p);
+ }
+
+ public String getID(){
+ return mId;
+ }
+
+ public VPath(Resources r, AttributeSet attrs) {
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawablePath);
+ mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, false);
+ mId = a.getString(R.styleable.VectorDrawablePath_name);
+ mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
+ mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, 0);
+ mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, Float.NaN);
+
+ if (!Float.isNaN(mFillOpacity)) {
+ mFillColor &= 0x00FFFFFF;
+ mFillColor |= ((int) (0xFF * mFillOpacity)) << 24;
+ }
+ mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, 0);
+ mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, 0);
+ mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, 0);
+ int lineCap = a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, 0);
+ switch (lineCap) {
+ case LINECAP_BUTT:
+ mStrokelineCap = Paint.Cap.BUTT;
+ break;
+ case LINECAP_ROUND:
+ mStrokelineCap = Paint.Cap.ROUND;
+ break;
+ case LINECAP_SQUARE:
+ mStrokelineCap = Paint.Cap.SQUARE;
+ break;
+ }
+ int lineJoin = a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, 0);
+ switch (lineJoin) {
+ case LINEJOIN_MITER:
+ mStrokelineJoin = Paint.Join.MITER;
+ break;
+ case LINEJOIN_ROUND:
+ mStrokelineJoin = Paint.Join.ROUND;
+ break;
+ case LINEJOIN_BEVEL:
+ mStrokelineJoin = Paint.Join.BEVEL;
+ break;
+ }
+ mStrokeMiterlimit = a.getFloat(R.styleable.VectorDrawablePath_strokeMiterLimit,
+ mStrokeMiterlimit);
+ mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
+ mStrokeOpacity = a.getFloat(R.styleable.VectorDrawablePath_strokeOpacity, Float.NaN);
+ if (!Float.isNaN(mStrokeOpacity)) {
+ mStrokeColor &= 0x00FFFFFF;
+ mStrokeColor |= ((int) (0xFF * mStrokeOpacity)) << 24;
+ }
+ mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, 0);
+ mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, 1);
+ mTrimPathOffset = a.getFloat(R.styleable.VectorDrawablePath_trimPathOffset, 0);
+ mTrimPathStart = a.getFloat(R.styleable.VectorDrawablePath_trimPathStart, 0);
+ int[] states = {R.styleable.VectorDrawablePath_state_activated,
+ R.styleable.VectorDrawablePath_state_checkable,
+ R.styleable.VectorDrawablePath_state_checked,
+ R.styleable.VectorDrawablePath_state_enabled,
+ R.styleable.VectorDrawablePath_state_focused,
+ R.styleable.VectorDrawablePath_state_hovered,
+ R.styleable.VectorDrawablePath_state_pressed,
+ R.styleable.VectorDrawablePath_state_selected,
+ R.styleable.VectorDrawablePath_state_window_focused};
+ for (int state : states) {
+ if (a.hasValue(state)) {
+ addStateFilter(state, a.getBoolean(state, false));
+ }
+ }
+ a.recycle();
+ }
+
+ private static int nextStart(String s, int end) {
+ char c;
+
+ while (end < s.length()) {
+ c = s.charAt(end);
+ if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) {
+ return end;
+ }
+ end++;
+ }
+ return end;
+ }
+
+ private void addNode(ArrayList<VectorDrawable.VNode> list, char cmd, float[] val) {
+ list.add(new VectorDrawable.VNode(cmd, val));
+ }
+
+ /**
+ * parse the floats in the string
+ * this is an optimized version of
+ * parseFloat(s.split(",|\\s"));
+ *
+ * @param s the string containing a command and list of floats
+ * @return array of floats
+ */
+ private static float[] getFloats(String s) {
+ if (s.charAt(0) == 'z' | s.charAt(0) == 'Z') {
+ return new float[0];
+ }
+ try {
+ float[] tmp = new float[s.length()];
+ int count = 0;
+ int pos = 1, end;
+ while ((end = extract(s, pos)) >= 0) {
+ if (pos < end) {
+ tmp[count++] = Float.parseFloat(s.substring(pos, end));
+ }
+ pos = end + 1;
+ }
+ // handle the final float if there is one
+ if (pos < s.length()) {
+ tmp[count++] = Float.parseFloat(s.substring(pos, s.length()));
+ }
+ return Arrays.copyOf(tmp, count);
+ } catch (NumberFormatException e){
+ Log.e(LOGTAG,"error in parsing \""+s+"\"");
+ throw e;
+ }
+ }
+
+ /**
+ * calculate the position of the next comma or space
+ * @param s the string to search
+ * @param start the position to start searching
+ * @return the position of the next comma or space or -1 if none found
+ */
+ private static int extract(String s, int start) {
+ int space = s.indexOf(' ', start);
+ int comma = s.indexOf(',', start);
+ if (space == -1) {
+ return comma;
+ }
+ if (comma == -1) {
+ return space;
+ }
+ return (comma > space) ? space : comma;
+ }
+
+ private VectorDrawable.VNode[] parsePath(String value) {
+ int start = 0;
+ int end = 1;
+
+ ArrayList<VectorDrawable.VNode> list = new ArrayList<VectorDrawable.VNode>();
+ while (end < value.length()) {
+ end = nextStart(value, end);
+ String s = value.substring(start, end);
+ float[] val = getFloats(s);
+ addNode(list, s.charAt(0), val);
+
+ start = end;
+ end++;
+ }
+ if ((end - start) == 1 && start < value.length()) {
+
+ addNode(list, value.charAt(start), new float[0]);
+ }
+ return list.toArray(new VectorDrawable.VNode[list.size()]);
+ }
+
+ public void copyFrom(VPath p1) {
+ mNode = new VNode[p1.mNode.length];
+ for (int i = 0; i < mNode.length; i++) {
+ mNode[i] = new VNode(p1.mNode[i]);
+ }
+ mId = p1.mId;
+ mStrokeColor = p1.mStrokeColor;
+ mFillColor = p1.mFillColor;
+ mStrokeWidth = p1.mStrokeWidth;
+ mRotate = p1.mRotate;
+ mPivotX = p1.mPivotX;
+ mPivotY = p1.mPivotY;
+ mAnimated = p1.mAnimated;
+ mTrimPathStart = p1.mTrimPathStart;
+ mTrimPathEnd = p1.mTrimPathEnd;
+ mTrimPathOffset = p1.mTrimPathOffset;
+ mStrokelineCap = p1.mStrokelineCap;
+ mStrokelineJoin = p1.mStrokelineJoin;
+ mStrokeMiterlimit = p1.mStrokeMiterlimit;
+ mNumberOfStates = p1.mNumberOfStates;
+ for (int i = 0; i < mNumberOfStates; i++) {
+ mCheckState[i] = p1.mCheckState[i];
+ mCheckValue[i] = p1.mCheckValue[i];
+ }
+
+ mFillRule = p1.mFillRule;
+ }
+
+ public static VPath interpolate(float t, VPath p1, VPath p2, VPath returnPath, int limit) {
+ if (limit == LIMIT_ALL || limit == LIMIT_PATH) {
+ if (returnPath.mNode == null || returnPath.mNode.length != p1.mNode.length) {
+ returnPath.mNode = new VNode[p1.mNode.length];
+ }
+ for (int i = 0; i < returnPath.mNode.length; i++) {
+ if (returnPath.mNode[i] == null) {
+ returnPath.mNode[i] = new VNode(p1.mNode[i], p2.mNode[i], t);
+ } else {
+ returnPath.mNode[i].interpolate(p1.mNode[i], p2.mNode[i], t);
+ }
+ }
+ }
+ float t1 = 1 - t;
+ switch (limit) {
+ case LIMIT_ALL:
+ returnPath.mRotate = t1 * p1.mRotate + t * p2.mRotate;
+ returnPath.mPivotX = t1 * p1.mPivotX + t * p2.mPivotX;
+ returnPath.mPivotY = t1 * p1.mPivotY + t * p2.mPivotY;
+ returnPath.mClip = p1.mClip | p2.mClip;
+
+ returnPath.mTrimPathStart = t1 * p1.mTrimPathStart + t * p2.mTrimPathStart;
+ returnPath.mTrimPathEnd = t1 * p1.mTrimPathEnd + t * p2.mTrimPathEnd;
+ returnPath.mTrimPathOffset = t1 * p1.mTrimPathOffset + t * p2.mTrimPathOffset;
+ returnPath.mStrokeMiterlimit =
+ t1 * p1.mStrokeMiterlimit + t * p2.mStrokeMiterlimit;
+ returnPath.mStrokelineCap = p1.mStrokelineCap;
+ if (returnPath.mStrokelineCap == null) {
+ returnPath.mStrokelineCap = p2.mStrokelineCap;
+ }
+ returnPath.mStrokelineJoin = p1.mStrokelineJoin;
+ if (returnPath.mStrokelineJoin == null) {
+ returnPath.mStrokelineJoin = p2.mStrokelineJoin;
+ }
+ returnPath.mFillRule = p1.mFillRule;
+
+ returnPath.mStrokeColor = rgbInterpolate(t, p1.mStrokeColor, p2.mStrokeColor);
+ returnPath.mFillColor = rgbInterpolate(t, p1.mFillColor, p2.mFillColor);
+ returnPath.mStrokeWidth = t1 * p1.mStrokeWidth + t * p2.mStrokeWidth;
+ returnPath.mNumberOfStates = p1.mNumberOfStates;
+ for (int i = 0; i < returnPath.mNumberOfStates; i++) {
+ returnPath.mCheckState[i] = p1.mCheckState[i];
+ returnPath.mCheckValue[i] = p1.mCheckValue[i];
+ }
+ for (int i = 0; i < p2.mNumberOfStates; i++) {
+ returnPath.addStateFilter(p2.mCheckState[i], p2.mCheckValue[i]);
+ }
+
+ int count = 0;
+ for (int i = 0; i < returnPath.mNumberOfStates; i++) {
+ if (returnPath.mCheckValue[i]) {
+ count++;
+ }
+ }
+ returnPath.mNumberOfTrue = count;
+ break;
+ case LIMIT_ROTATE:
+ returnPath.mRotate = t1 * p1.mRotate + t * p2.mRotate;
+ break;
+ case LIMIT_TRIM_PATH_END:
+ returnPath.mTrimPathEnd = t1 * p1.mTrimPathEnd + t * p2.mTrimPathEnd;
+ break;
+ case LIMIT_TRIM_PATH_OFFSET:
+ returnPath.mTrimPathOffset = t1 * p1.mTrimPathOffset + t * p2.mTrimPathOffset;
+ break;
+ case LIMIT_TRIM_PATH_START:
+ returnPath.mTrimPathStart = t1 * p1.mTrimPathStart + t * p2.mTrimPathStart;
+ break;
+ }
+ return returnPath;
+ }
+
+ private static int rgbInterpolate(float t, int color1, int color2) {
+ int ret;
+ if (color1 == color2) {
+ return color2;
+ }
+ if (color1 == 0) {
+ return color2;
+ }
+ if (color2 == 0) {
+ return color1;
+ }
+
+ float t1 = 1 - t;
+ ret = 0xFF & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)));
+ color1 >>= 8;
+ color2 >>= 8;
+
+ ret |= 0xFF00 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 8);
+ color1 >>= 8;
+ color2 >>= 8;
+ ret |= 0xFF0000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 16);
+ color1 >>= 8;
+ color2 >>= 8;
+ ret |= 0xFF000000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 24);
+
+ return ret;
+ }
+
+ public boolean isVisible(int[] state) {
+ int match = 0;
+ for (int i = 0; i < state.length; i++) {
+ int v = getState(state[i]);
+ if (v != STATE_UNDEFINED) {
+ if (v==STATE_TRUE) {
+ match++;
+ } else {
+ return false;
+ }
+ }
+ }
+ return match == mNumberOfTrue;
+ }
+ }
+
+ private static class VNode {
+ char type;
+ float[] params;
+ private static float[] current = new float[4];
+ public VNode(char type, float[] params) {
+ this.type = type;
+ this.params = params;
+ }
+
+ public VNode(VNode n) {
+ this.type = n.type;
+ this.params = Arrays.copyOf(n.params, n.params.length);
+ }
+
+ public VNode(VNode n1, VNode n2, float t) {
+ this.type = n1.type;
+ this.params = new float[n1.params.length];
+ interpolate(n1, n2, t);
+ }
+
+ private boolean match(VNode n) {
+ if (n.type != type) {
+ return false;
+ }
+ return (params.length == n.params.length);
+ }
+
+ public void interpolate(VNode n1, VNode n2, float t) {
+ for (int i = 0; i < n1.params.length; i++) {
+ params[i] = n1.params[i] * (1 - t) + n2.params[i] * t;
+ }
+ }
+
+ private void nodeListToPath(VNode[] node, Path path) {
+ float[] current = new float[4];
+ for (int i = 0; i < node.length; i++) {
+ addCommand(path, current, node[i].type, node[i].params);
+ }
+ }
+
+ public static void createPath(VNode[] node, Path path) {
+ Arrays.fill(current,0);
+ for (int i = 0; i < node.length; i++) {
+ addCommand(path, current, node[i].type, node[i].params);
+ }
+ }
+
+ private static void addCommand(Path path, float[] current, char cmd, float[] val) {
+
+ int incr = 2;
+ float currentX = current[0];
+ float currentY = current[1];
+ float ctrlPointX = current[2];
+ float ctrlPointY = current[3];
+
+ switch (cmd) {
+ case 'z':
+ case 'Z':
+ path.close();
+ return;
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ case 't':
+ case 'T':
+ incr = 2;
+ break;
+ case 'h':
+ case 'H':
+ case 'v':
+ case 'V':
+ incr = 1;
+ break;
+ case 'c':
+ case 'C':
+ incr = 6;
+ break;
+ case 's':
+ case 'S':
+ case 'q':
+ case 'Q':
+ incr = 4;
+ break;
+ case 'a':
+ case 'A':
+ incr = 7;
+ break;
+ }
+ for (int k = 0; k < val.length; k += incr) {
+ // TODO: build test to prove all permutations work
+ switch (cmd) {
+ case 'm': // moveto - Start a new sub-path (relative)
+ path.rMoveTo(val[k + 0], val[k + 1]);
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+ break;
+ case 'M': // moveto - Start a new sub-path
+ path.moveTo(val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+ break;
+ case 'l': // lineto - Draw a line from the current point (relative)
+ path.rLineTo(val[k + 0], val[k + 1]);
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+ break;
+ case 'L': // lineto - Draw a line from the current point
+ path.lineTo(val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+ break;
+ case 'z': // closepath - Close the current subpath
+ case 'Z': // closepath - Close the current subpath
+ path.close();
+ break;
+ case 'h': // horizontal lineto - Draws a horizontal line (relative)
+ path.rLineTo(val[k + 0], 0);
+ currentX += val[k + 0];
+ break;
+ case 'H': // horizontal lineto - Draws a horizontal line
+ path.lineTo(val[k + 0], currentY);
+ currentX = val[k + 0];
+ break;
+ case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+ path.rLineTo(0, val[k + 0]);
+ currentY += val[k + 0];
+ break;
+ case 'V': // vertical lineto - Draws a vertical line from the current point
+ path.lineTo(currentX, val[k + 0]);
+ currentY = val[k + 0];
+ break;
+ case 'c': // curveto - Draws a cubic Bézier curve (relative)
+ path.rCubicTo(val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3],
+ val[k + 4],
+ val[k + 5]);
+
+ ctrlPointX = currentX + val[k + 2];
+ ctrlPointY = currentY + val[k + 3];
+ currentX += val[k + 4];
+ currentY += val[k + 5];
+
+ break;
+ case 'C': // curveto - Draws a cubic Bézier curve
+ path.cubicTo(val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3],
+ val[k + 4],
+ val[k + 5]);
+ currentX = val[k + 4];
+ currentY = val[k + 5];
+ ctrlPointX = val[k + 2];
+ ctrlPointY = val[k + 3];
+
+ break;
+ case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+ path.rCubicTo(currentX - ctrlPointX, currentY - ctrlPointY,
+ val[k + 0], val[k + 1],
+ val[k + 2], val[k + 3]);
+
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ break;
+ case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+ path.cubicTo(2 * currentX - ctrlPointX,
+ 2 * currentY - ctrlPointY,
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3]);
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ break;
+ case 'q': // Draws a quadratic Bézier (relative)
+ path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ break;
+ case 'Q': // Draws a quadratic Bézier
+ path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ break;
+ case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+ path.rQuadTo(currentX - ctrlPointX, currentY - ctrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = ctrlPointX + currentX;
+ ctrlPointY = ctrlPointY + currentY;
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+
+ break;
+ case 'T': // Draws a quadratic Bézier curve (reflective control point)
+ path.quadTo(currentX * 2 - ctrlPointX, currentY * 2 - ctrlPointY,
+ val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1]; // TODO: Check this logic
+ ctrlPointX = -(val[k + 0] - currentX);
+ ctrlPointY = -(val[k + 1] - currentY);
+ break;
+ case 'a': // Draws an elliptical arc
+ // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5] + currentX,
+ val[k + 6] + currentY,
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
+ val[k + 4] != 0);
+ currentX += val[k + 5];
+ currentY += val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+
+ break;
+ case 'A': // Draws an elliptical arc
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5],
+ val[k + 6],
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
+ val[k + 4] != 0);
+ currentX = val[k + 5];
+ currentY = val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+ break;
+ }
+ }
+ current[0] = currentX;
+ current[1] = currentY;
+ current[2] = ctrlPointX;
+ current[3] = ctrlPointY;
+ }
+
+ private static void drawArc(Path p,
+ float x0,
+ float y0,
+ float x1,
+ float y1,
+ float a,
+ float b,
+ float theta,
+ boolean isMoreThanHalf,
+ boolean isPositiveArc) {
+
+ /* Convert rotation angle from degrees to radians */
+ double thetaD = Math.toRadians(theta);
+ /* Pre-compute rotation matrix entries */
+ double cosTheta = Math.cos(thetaD);
+ double sinTheta = Math.sin(thetaD);
+ /* Transform (x0, y0) and (x1, y1) into unit space */
+ /* using (inverse) rotation, followed by (inverse) scale */
+ double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
+ double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
+ double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
+ double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
+
+ /* Compute differences and averages */
+ double dx = x0p - x1p;
+ double dy = y0p - y1p;
+ double xm = (x0p + x1p) / 2;
+ double ym = (y0p + y1p) / 2;
+ /* Solve for intersecting unit circles */
+ double dsq = dx * dx + dy * dy;
+ if (dsq == 0.0) {
+ Log.w(LOGTAG, " Points are coincident");
+ return; /* Points are coincident */
+ }
+ double disc = 1.0 / dsq - 1.0 / 4.0;
+ if (disc < 0.0) {
+ Log.w(LOGTAG, "Points are too far apart " + dsq);
+ float adjust = (float) (Math.sqrt(dsq) / 1.99999);
+ drawArc(p, x0, y0, x1, y1, a * adjust,
+ b * adjust, theta, isMoreThanHalf, isPositiveArc);
+ return; /* Points are too far apart */
+ }
+ double s = Math.sqrt(disc);
+ double sdx = s * dx;
+ double sdy = s * dy;
+ double cx;
+ double cy;
+ if (isMoreThanHalf == isPositiveArc) {
+ cx = xm - sdy;
+ cy = ym + sdx;
+ } else {
+ cx = xm + sdy;
+ cy = ym - sdx;
+ }
+
+ double eta0 = Math.atan2((y0p - cy), (x0p - cx));
+
+ double eta1 = Math.atan2((y1p - cy), (x1p - cx));
+
+ double sweep = (eta1 - eta0);
+ if (isPositiveArc != (sweep >= 0)) {
+ if (sweep > 0) {
+ sweep -= 2 * Math.PI;
+ } else {
+ sweep += 2 * Math.PI;
+ }
+ }
+
+ cx *= a;
+ cy *= b;
+ double tcx = cx;
+ cx = cx * cosTheta - cy * sinTheta;
+ cy = tcx * sinTheta + cy * cosTheta;
+
+ arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
+ }
+
+ /**
+ * Converts an arc to cubic Bezier segments and records them in p.
+ *
+ * @param p The target for the cubic Bezier segments
+ * @param cx The x coordinate center of the ellipse
+ * @param cy The y coordinate center of the ellipse
+ * @param a The radius of the ellipse in the horizontal direction
+ * @param b The radius of the ellipse in the vertical direction
+ * @param e1x E(eta1) x coordinate of the starting point of the arc
+ * @param e1y E(eta2) y coordinate of the starting point of the arc
+ * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane
+ * @param start The start angle of the arc on the ellipse
+ * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
+ */
+ private static void arcToBezier(Path p,
+ double cx,
+ double cy,
+ double a,
+ double b,
+ double e1x,
+ double e1y,
+ double theta,
+ double start,
+ double sweep) {
+ // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html
+ // and http://www.spaceroots.org/documents/ellipse/node22.html
+
+ // Maximum of 45 degrees per cubic Bezier segment
+ int numSegments = Math.abs((int) Math.ceil(sweep * 4 / Math.PI));
+
+ double eta1 = start;
+ double cosTheta = Math.cos(theta);
+ double sinTheta = Math.sin(theta);
+ double cosEta1 = Math.cos(eta1);
+ double sinEta1 = Math.sin(eta1);
+ double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
+ double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
+
+ double anglePerSegment = sweep / numSegments;
+ for (int i = 0; i < numSegments; i++) {
+ double eta2 = eta1 + anglePerSegment;
+ double sinEta2 = Math.sin(eta2);
+ double cosEta2 = Math.cos(eta2);
+ double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2);
+ double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2);
+ double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
+ double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
+ double tanDiff2 = Math.tan((eta2 - eta1) / 2);
+ double alpha =
+ Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
+ double q1x = e1x + alpha * ep1x;
+ double q1y = e1y + alpha * ep1y;
+ double q2x = e2x - alpha * ep2x;
+ double q2y = e2y - alpha * ep2y;
+
+ p.cubicTo((float) q1x,
+ (float) q1y,
+ (float) q2x,
+ (float) q2y,
+ (float) e2x,
+ (float) e2y);
+ eta1 = eta2;
+ e1x = e2x;
+ e1y = e2y;
+ ep1x = ep2x;
+ ep1y = ep2y;
+ }
+ }
+
+ }
+}
diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp
index a5b9416..d16d5498 100644
--- a/libs/androidfw/BackupData.cpp
+++ b/libs/androidfw/BackupData.cpp
@@ -79,7 +79,7 @@ BackupDataWriter::write_padding_for(int n)
paddingSize = padding_extra(n);
if (paddingSize > 0) {
uint32_t padding = 0xbcbcbcbc;
- if (DEBUG) ALOGI("writing %d padding bytes for %d", paddingSize, n);
+ if (DEBUG) ALOGI("writing %zd padding bytes for %d", paddingSize, n);
amt = write(m_fd, &padding, paddingSize);
if (amt != paddingSize) {
m_status = errno;
@@ -113,7 +113,7 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
k = key;
}
if (DEBUG) {
- ALOGD("Writing header: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(),
+ ALOGD("Writing header: prefix='%s' key='%s' dataSize=%zu", m_keyPrefix.string(),
key.string(), dataSize);
}
@@ -126,7 +126,7 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
header.keyLen = tolel(keyLen);
header.dataSize = tolel(dataSize);
- if (DEBUG) ALOGI("writing entity header, %d bytes", sizeof(entity_header_v1));
+ if (DEBUG) ALOGI("writing entity header, %zu bytes", sizeof(entity_header_v1));
amt = write(m_fd, &header, sizeof(entity_header_v1));
if (amt != sizeof(entity_header_v1)) {
m_status = errno;
@@ -134,7 +134,7 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
}
m_pos += amt;
- if (DEBUG) ALOGI("writing entity header key, %d bytes", keyLen+1);
+ if (DEBUG) ALOGI("writing entity header key, %zd bytes", keyLen+1);
amt = write(m_fd, k.string(), keyLen+1);
if (amt != keyLen+1) {
m_status = errno;
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index ab837ad..52dce9f 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -639,7 +639,7 @@ int write_tarfile(const String8& packageName, const String8& domain,
// size header -- calc len in digits by actually rendering the number
// to a string - brute force but simple
- snprintf(sizeStr, sizeof(sizeStr), "%lld", s.st_size);
+ snprintf(sizeStr, sizeof(sizeStr), "%lld", (long long)s.st_size);
p += write_pax_header_entry(p, "size", sizeStr);
// fullname was generated above with the ustar paths
@@ -661,7 +661,7 @@ int write_tarfile(const String8& packageName, const String8& domain,
// [ 124 : 12 ] size of pax extended header data
memset(paxHeader + 124, 0, 12);
- snprintf(paxHeader + 124, 12, "%011o", p - paxData);
+ snprintf(paxHeader + 124, 12, "%011o", (unsigned int)(p - paxData));
// Checksum and write the pax block header
calc_tar_checksum(paxHeader);
@@ -681,7 +681,10 @@ int write_tarfile(const String8& packageName, const String8& domain,
if (!isdir) {
off64_t toWrite = s.st_size;
while (toWrite > 0) {
- size_t toRead = (toWrite < BUFSIZE) ? toWrite : BUFSIZE;
+ size_t toRead = toWrite;
+ if (toRead > BUFSIZE) {
+ toRead = BUFSIZE;
+ }
ssize_t nRead = read(fd, buf, toRead);
if (nRead < 0) {
err = errno;
@@ -1095,8 +1098,8 @@ backup_helper_test_four()
if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
|| states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
|| states[i].size != state.size || states[i].crc32 != states[i].crc32) {
- fprintf(stderr, "state %zu expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
- " actual={%d/%d, 0x%08x, %04o, 0x%08x, %3zu} '%s'\n", i,
+ fprintf(stderr, "state %zu expected={%d/%d, %04o, 0x%08x, 0x%08x, %3zu} '%s'\n"
+ " actual={%d/%d, %04o, 0x%08x, 0x%08x, %3d} '%s'\n", i,
states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
states[i].crc32, name.length(), filenames[i].string(),
state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
@@ -1194,7 +1197,7 @@ int
test_read_header_and_entity(BackupDataReader& reader, const char* str)
{
int err;
- int bufSize = strlen(str)+1;
+ size_t bufSize = strlen(str)+1;
char* buf = (char*)malloc(bufSize);
String8 string;
int cookie = 0x11111111;
@@ -1229,9 +1232,9 @@ test_read_header_and_entity(BackupDataReader& reader, const char* str)
err = EINVAL;
goto finished;
}
- if ((int)actualSize != bufSize) {
- fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08zx\n", bufSize,
- actualSize);
+ if (actualSize != bufSize) {
+ fprintf(stderr, "ReadEntityHeader expected dataSize %zu got %zu\n",
+ bufSize, actualSize);
err = EINVAL;
goto finished;
}
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 2b74a33..166863c 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -210,8 +210,8 @@ uint32_t CursorWindow::alloc(size_t size, bool aligned) {
uint32_t offset = mHeader->freeOffset + padding;
uint32_t nextFreeOffset = offset + size;
if (nextFreeOffset > mSize) {
- ALOGW("Window is full: requested allocation %d bytes, "
- "free space %d bytes, window size %d bytes",
+ ALOGW("Window is full: requested allocation %zu bytes, "
+ "free space %zu bytes, window size %zu bytes",
size, freeSpace(), mSize);
return 0;
}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 04ca81e..7616ab0 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -6251,12 +6251,12 @@ void ResTable::print(bool inclValues) const
uintptr_t esize = dtohs(ent->size);
if ((esize&0x3) != 0) {
- printf("NON-INTEGER ResTable_entry SIZE: 0x%x\n", esize);
+ printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize);
continue;
}
if ((thisOffset+esize) > typeSize) {
- printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+0x%x (size is 0x%x)\n",
- entriesStart, thisOffset, esize, typeSize);
+ printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+%p (size is 0x%x)\n",
+ entriesStart, thisOffset, (void *)esize, typeSize);
continue;
}
diff --git a/libs/common_time/common_time_server.cpp b/libs/common_time/common_time_server.cpp
index 21e706f..3e11987 100644
--- a/libs/common_time/common_time_server.cpp
+++ b/libs/common_time/common_time_server.cpp
@@ -590,7 +590,7 @@ static void hexDumpToString(const uint8_t* src, size_t src_len,
for (i = 0; (i < src_len) && (offset < dst_len); ++i) {
int res;
if (0 == (i % 16)) {
- res = snprintf(dst + offset, dst_len - offset, "\n%04x :", i);
+ res = snprintf(dst + offset, dst_len - offset, "\n%04zx :", i);
if (res < 0)
break;
offset += res;
diff --git a/libs/common_time/utils.cpp b/libs/common_time/utils.cpp
index ed2c77d..ddcdfe7 100644
--- a/libs/common_time/utils.cpp
+++ b/libs/common_time/utils.cpp
@@ -56,7 +56,7 @@ LogRing::LogRing(const char* header, size_t entries)
, mHeader(header) {
mRingBuffer = new Entry[mSize];
if (NULL == mRingBuffer)
- ALOGE("Failed to allocate log ring with %u entries.", mSize);
+ ALOGE("Failed to allocate log ring with %zu entries.", mSize);
}
LogRing::~LogRing() {
@@ -150,7 +150,7 @@ void LogRing::dumpLog(int fd) {
localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t);
strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
- res = snprintf(buf, sizeof(buf), "[%2d] %s.%03ld :: %s%s\n",
+ res = snprintf(buf, sizeof(buf), "[%2zu] %s.%03ld :: %s%s\n",
i, timebuf,
mRingBuffer[ndx].first_ts.tv_usec / 1000,
mRingBuffer[ndx].s.string(),
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 4de755d..52be531 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -54,6 +54,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
# RenderThread stuff
LOCAL_SRC_FILES += \
renderthread/CanvasContext.cpp \
+ renderthread/DrawFrameTask.cpp \
renderthread/RenderProxy.cpp \
renderthread/RenderTask.cpp \
renderthread/RenderThread.cpp
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 7380bbf..5b4e03f 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -29,7 +29,6 @@ DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, OpenGLRenderer* rendere
, mNeedsGLContextAttach(false)
, mUpdateTexImage(false)
, mLayer(layer)
- , mRenderer(renderer)
, mCaches(Caches::getInstance()) {
mWidth = mLayer->layer.getWidth();
mHeight = mLayer->layer.getHeight();
@@ -45,7 +44,6 @@ DeferredLayerUpdater::~DeferredLayerUpdater() {
if (mLayer) {
mCaches.resourceCache.decrementRefcount(mLayer);
}
- delete mRenderer;
}
void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
@@ -76,7 +74,7 @@ bool DeferredLayerUpdater::apply() {
}
mLayer->setBlend(mBlend);
mDisplayList->updateProperties();
- mLayer->updateDeferred(mRenderer, mDisplayList,
+ mLayer->updateDeferred(mDisplayList,
mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
mDirtyRect.setEmpty();
mDisplayList = 0;
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index cf745ee..10fa264 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -109,7 +109,6 @@ private:
bool mUpdateTexImage;
Layer* mLayer;
- OpenGLRenderer* mRenderer;
Caches& mCaches;
void doUpdateTexImage();
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 9e367fc..5fa8f1d 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1499,13 +1499,13 @@ public:
virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
bool useQuickReject) {
if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
- mDisplayList->defer(deferStruct, level + 1);
+ mDisplayList->deferNodeInParent(deferStruct, level + 1);
}
}
virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
bool useQuickReject) {
if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
- mDisplayList->replay(replayStruct, level + 1);
+ mDisplayList->replayNodeInParent(replayStruct, level + 1);
}
}
@@ -1548,14 +1548,16 @@ private:
};
/**
- * Not a canvas operation, used only by 3d / z ordering logic in DisplayList::iterate()
+ * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
*/
class DrawShadowOp : public DrawOp {
public:
- DrawShadowOp(const mat4& transformXY, const mat4& transformZ, float alpha,
+ DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
+ float casterAlpha, bool casterUnclipped,
float fallbackWidth, float fallbackHeight,
const SkPath* outline, const SkPath* revealClip)
- : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ), mAlpha(alpha),
+ : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ),
+ mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped),
mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight),
mOutline(outline), mRevealClip(revealClip) {}
@@ -1572,7 +1574,8 @@ public:
Op(casterPerimeter, *mRevealClip, kIntersect_PathOp, &casterPerimeter);
}
- return renderer.drawShadow(mTransformXY, mTransformZ, mAlpha, &casterPerimeter);
+ return renderer.drawShadow(mTransformXY, mTransformZ,
+ mCasterAlpha, mCasterUnclipped, &casterPerimeter);
}
virtual void output(int level, uint32_t logFlags) const {
@@ -1584,7 +1587,8 @@ public:
private:
const mat4 mTransformXY;
const mat4 mTransformZ;
- const float mAlpha;
+ const float mCasterAlpha;
+ const bool mCasterUnclipped;
const float mFallbackWidth;
const float mFallbackHeight;
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index bd9bfe9..27409a2 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -58,6 +58,7 @@ Layer::~Layer() {
delete[] mesh;
delete deferredList;
+ delete renderer;
}
uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
@@ -68,6 +69,13 @@ uint32_t Layer::computeIdealHeight(uint32_t layerHeight) {
return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE);
}
+void Layer::requireRenderer() {
+ if (!renderer) {
+ renderer = new LayerRenderer(this);
+ renderer->initProperties();
+ }
+}
+
bool Layer::resize(const uint32_t width, const uint32_t height) {
uint32_t desiredWidth = computeIdealWidth(width);
uint32_t desiredHeight = computeIdealWidth(height);
@@ -201,13 +209,12 @@ void Layer::defer() {
dirtyRect.right, dirtyRect.bottom, !isBlend());
displayList->computeOrdering();
- displayList->defer(deferredState, 0);
+ displayList->deferNodeTree(deferredState);
deferredUpdateScheduled = false;
}
void Layer::cancelDefer() {
- renderer = NULL;
displayList = NULL;
deferredUpdateScheduled = false;
if (deferredList) {
@@ -226,7 +233,6 @@ void Layer::flush() {
deferredList->flush(*renderer, dirtyRect);
renderer->finish();
- renderer = NULL;
dirtyRect.setEmpty();
displayList = NULL;
@@ -241,7 +247,6 @@ void Layer::render() {
renderer->drawDisplayList(displayList, dirtyRect, RenderNode::kReplayFlag_ClipChildren);
renderer->finish();
- renderer = NULL;
dirtyRect.setEmpty();
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index d8440ea..b428404 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -84,9 +84,9 @@ public:
regionRect.translate(layer.left, layer.top);
}
- void updateDeferred(OpenGLRenderer* renderer, RenderNode* displayList,
+ void updateDeferred(RenderNode* displayList,
int left, int top, int right, int bottom) {
- this->renderer = renderer;
+ requireRenderer();
this->displayList = displayList;
const Rect r(left, top, right, bottom);
dirtyRect.unionWith(r);
@@ -300,6 +300,8 @@ public:
bool hasDrawnSinceUpdate;
private:
+ void requireRenderer();
+
Caches& caches;
/**
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index d808735..125dfda 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1924,14 +1924,14 @@ status_t OpenGLRenderer::drawDisplayList(RenderNode* displayList, Rect& dirty,
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
status = startFrame();
ReplayStateStruct replayStruct(*this, dirty, replayFlags);
- displayList->replay(replayStruct, 0);
+ displayList->replayNodeTree(replayStruct);
return status | replayStruct.mDrawGlStatus;
}
bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs!
DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw);
DeferStateStruct deferStruct(deferredList, *this, replayFlags);
- displayList->defer(deferStruct, 0);
+ displayList->deferNodeTree(deferStruct);
flushLayers();
status = startFrame();
@@ -3203,7 +3203,7 @@ static void mapPointFakeZ(Vector3& point, const mat4& transformXY, const mat4& t
}
status_t OpenGLRenderer::drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
- float casterAlpha, const SkPath* casterPerimeter) {
+ float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter) {
if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
// TODO: use quickRejectWithScissor. For now, always force enable scissor.
@@ -3260,7 +3260,7 @@ status_t OpenGLRenderer::drawShadow(const mat4& casterTransformXY, const mat4& c
Rect casterBounds(casterPerimeter->getBounds());
casterTransformXY.mapRect(casterBounds);
- bool isCasterOpaque = (casterAlpha == 1.0f);
+ bool isCasterOpaque = (casterAlpha == 1.0f) && casterUnclipped;
// draw caster's shadows
if (mCaches.propertyAmbientShadowStrength > 0) {
paint.setARGB(casterAlpha * mCaches.propertyAmbientShadowStrength, 0, 0, 0);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 054767e..2debd2e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -210,7 +210,7 @@ public:
virtual status_t drawRects(const float* rects, int count, const SkPaint* paint);
status_t drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
- float casterAlpha, const SkPath* casterPerimeter);
+ float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter);
virtual void resetShader();
virtual void setupShader(SkiaShader* shader);
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index e39e5ae..34d98a1 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -107,6 +107,23 @@ void RenderNode::updateProperties() {
}
}
+bool RenderNode::hasFunctors() {
+ if (!mDisplayListData) return false;
+
+ if (mDisplayListData->functorCount) {
+ return true;
+ }
+
+ for (size_t i = 0; i < mDisplayListData->children.size(); i++) {
+ RenderNode* childNode = mDisplayListData->children[i]->mDisplayList;
+ if (childNode->hasFunctors()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/*
* For property operations, we pass a savecount of 0, since the operations aren't part of the
* displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in
@@ -115,10 +132,9 @@ void RenderNode::updateProperties() {
#define PROPERTY_SAVECOUNT 0
template <class T>
-void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler,
- const int level) {
+void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) {
#if DEBUG_DISPLAY_LIST
- properties().debugOutputProperties(level);
+ properties().debugOutputProperties(handler.level() + 1);
#endif
if (properties().getLeft() != 0 || properties().getTop() != 0) {
renderer.translate(properties().getLeft(), properties().getTop());
@@ -285,7 +301,6 @@ void RenderNode::computeOrderingImpl(
child->computeOrderingImpl(childOp, projectionChildren, projectionTransform);
}
}
-
}
class DeferOperationHandler {
@@ -296,15 +311,25 @@ public:
operation->defer(mDeferStruct, saveCount, mLevel, clipToBounds);
}
inline LinearAllocator& allocator() { return *(mDeferStruct.mAllocator); }
+ inline void startMark(const char* name) {} // do nothing
+ inline void endMark() {}
+ inline int level() { return mLevel; }
+ inline int replayFlags() { return mDeferStruct.mReplayFlags; }
private:
DeferStateStruct& mDeferStruct;
const int mLevel;
};
-void RenderNode::defer(DeferStateStruct& deferStruct, const int level) {
+void RenderNode::deferNodeTree(DeferStateStruct& deferStruct) {
+ DeferOperationHandler handler(deferStruct, 0);
+ if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler);
+ issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
+}
+
+void RenderNode::deferNodeInParent(DeferStateStruct& deferStruct, const int level) {
DeferOperationHandler handler(deferStruct, level);
- iterate<DeferOperationHandler>(deferStruct.mRenderer, handler, level);
+ issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
}
class ReplayOperationHandler {
@@ -318,21 +343,31 @@ public:
operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds);
}
inline LinearAllocator& allocator() { return *(mReplayStruct.mAllocator); }
+ inline void startMark(const char* name) {
+ mReplayStruct.mRenderer.startMark(name);
+ }
+ inline void endMark() {
+ mReplayStruct.mRenderer.endMark();
+ DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(),
+ mReplayStruct.mDrawGlStatus);
+ }
+ inline int level() { return mLevel; }
+ inline int replayFlags() { return mReplayStruct.mReplayFlags; }
private:
ReplayStateStruct& mReplayStruct;
const int mLevel;
};
-void RenderNode::replay(ReplayStateStruct& replayStruct, const int level) {
- ReplayOperationHandler handler(replayStruct, level);
-
- replayStruct.mRenderer.startMark(mName.string());
- iterate<ReplayOperationHandler>(replayStruct.mRenderer, handler, level);
- replayStruct.mRenderer.endMark();
+void RenderNode::replayNodeTree(ReplayStateStruct& replayStruct) {
+ ReplayOperationHandler handler(replayStruct, 0);
+ if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler);
+ issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
+}
- DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(),
- replayStruct.mDrawGlStatus);
+void RenderNode::replayNodeInParent(ReplayStateStruct& replayStruct, const int level) {
+ ReplayOperationHandler handler(replayStruct, level);
+ issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
}
void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes) {
@@ -356,10 +391,42 @@ void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslat
std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end());
}
+template <class T>
+void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler) {
+ if (properties().getAlpha() <= 0.0f) return;
+
+ mat4 shadowMatrixXY(transformFromParent);
+ applyViewPropertyTransforms(shadowMatrixXY);
+
+ // Z matrix needs actual 3d transformation, so mapped z values will be correct
+ mat4 shadowMatrixZ(transformFromParent);
+ applyViewPropertyTransforms(shadowMatrixZ, true);
+
+ const SkPath* outlinePath = properties().getOutline().getPath();
+ const RevealClip& revealClip = properties().getRevealClip();
+ const SkPath* revealClipPath = revealClip.hasConvexClip()
+ ? revealClip.getPath() : NULL; // only pass the reveal clip's path if it's convex
+
+ /**
+ * The drawing area of the caster is always the same as the its perimeter (which
+ * the shadow system uses) *except* in the inverse clip case. Inform the shadow
+ * system that the caster's drawing area (as opposed to its perimeter) has been
+ * clipped, so that it knows the caster can't be opaque.
+ */
+ bool casterUnclipped = !revealClip.willClip() || revealClip.hasConvexClip();
+
+ DisplayListOp* shadowOp = new (handler.allocator()) DrawShadowOp(
+ shadowMatrixXY, shadowMatrixZ,
+ properties().getAlpha(), casterUnclipped,
+ properties().getWidth(), properties().getHeight(),
+ outlinePath, revealClipPath);
+ handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
+}
+
#define SHADOW_DELTA 0.1f
template <class T>
-void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+void RenderNode::issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler) {
const int size = zTranslatedNodes.size();
if (size == 0
@@ -369,12 +436,6 @@ void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTransl
return;
}
- int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- LinearAllocator& alloc = handler.allocator();
- ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().getWidth(), properties().getHeight(),
- SkRegion::kIntersect_Op); // clip to 3d root bounds
- handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
/**
* Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
* with very similar Z heights to draw together.
@@ -402,26 +463,7 @@ void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTransl
// attempt to render the shadow if the caster about to be drawn is its caster,
// OR if its caster's Z value is similar to the previous potential caster
if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) {
-
- if (caster->properties().getAlpha() > 0.0f) {
- mat4 shadowMatrixXY(casterOp->mTransformFromParent);
- caster->applyViewPropertyTransforms(shadowMatrixXY);
-
- // Z matrix needs actual 3d transformation, so mapped z values will be correct
- mat4 shadowMatrixZ(casterOp->mTransformFromParent);
- caster->applyViewPropertyTransforms(shadowMatrixZ, true);
-
- const SkPath* outlinePath = caster->properties().getOutline().getPath();
- const RevealClip& revealClip = caster->properties().getRevealClip();
- const SkPath* revealClipPath = revealClip.hasConvexClip()
- ? revealClip.getPath() : NULL; // only pass the reveal clip's path if it's convex
-
- DisplayListOp* shadowOp = new (alloc) DrawShadowOp(
- shadowMatrixXY, shadowMatrixZ, caster->properties().getAlpha(),
- caster->properties().getWidth(), caster->properties().getHeight(),
- outlinePath, revealClipPath);
- handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
- }
+ caster->issueDrawShadowOperation(casterOp->mTransformFromParent, handler);
lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
shadowIndex++;
@@ -444,17 +486,10 @@ void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTransl
renderer.restoreToCount(restoreTo);
drawIndex++;
}
- handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
template <class T>
-void RenderNode::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level) {
- int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- LinearAllocator& alloc = handler.allocator();
- ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().getWidth(), properties().getHeight(),
- SkRegion::kReplace_Op); // clip to projection surface root bounds
- handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
+void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler) {
for (size_t i = 0; i < mProjectedNodes.size(); i++) {
DrawDisplayListOp* childOp = mProjectedNodes[i];
@@ -466,7 +501,6 @@ void RenderNode::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler,
childOp->mSkipInOrderDraw = true;
renderer.restoreToCount(restoreTo);
}
- handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
/**
@@ -479,7 +513,8 @@ void RenderNode::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler,
* defer vs replay logic, per operation
*/
template <class T>
-void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level) {
+void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
+ const int level = handler.level();
if (CC_UNLIKELY(mDestroyed)) { // temporary debug logging
ALOGW("Error: %s is drawing after destruction", mName.string());
CRASH();
@@ -489,6 +524,8 @@ void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level)
return;
}
+ handler.startMark(mName.string());
+
#if DEBUG_DISPLAY_LIST
Rect* clipRect = renderer.getClipRect();
DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.0f, %.0f, %.0f",
@@ -504,7 +541,7 @@ void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level)
DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "",
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
- setViewProperties<T>(renderer, handler, level + 1);
+ setViewProperties<T>(renderer, handler);
bool quickRejected = properties().getClipToBounds()
&& renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
@@ -513,7 +550,7 @@ void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level)
buildZSortedChildList(zTranslatedNodes);
// for 3d root, draw children with negative z values
- iterate3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
+ issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
const int saveCountOffset = renderer.getSaveCount() - 1;
@@ -524,23 +561,24 @@ void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level)
#if DEBUG_DISPLAY_LIST
op->output(level + 1);
#endif
-
logBuffer.writeCommand(level, op->name());
handler(op, saveCountOffset, properties().getClipToBounds());
if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) {
- iterateProjectedChildren(renderer, handler, level);
+ issueOperationsOfProjectedChildren(renderer, handler);
}
}
// for 3d root, draw children with positive z values
- iterate3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
+ issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
}
DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
handler(new (alloc) RestoreToCountOp(restoreTo),
PROPERTY_SAVECOUNT, properties().getClipToBounds());
renderer.setOverrideLayerAlpha(1.0f);
+
+ handler.endMark();
}
} /* namespace uirenderer */
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 756c944..fb5336d 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -92,8 +92,12 @@ public:
ANDROID_API void setData(DisplayListData* newData);
void computeOrdering();
- void defer(DeferStateStruct& deferStruct, const int level);
- void replay(ReplayStateStruct& replayStruct, const int level);
+
+ void deferNodeTree(DeferStateStruct& deferStruct);
+ void deferNodeInParent(DeferStateStruct& deferStruct, const int level);
+
+ void replayNodeTree(ReplayStateStruct& replayStruct);
+ void replayNodeInParent(ReplayStateStruct& replayStruct, const int level);
ANDROID_API void output(uint32_t level = 1);
@@ -139,6 +143,9 @@ public:
ANDROID_API void updateProperties();
+ // Returns true if this RenderNode or any of its children have functors
+ bool hasFunctors();
+
private:
typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
@@ -161,19 +168,26 @@ private:
const mat4* transformFromProjectionSurface);
template <class T>
- inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level);
+ inline void setViewProperties(OpenGLRenderer& renderer, T& handler);
void buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes);
+ template<class T>
+ inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
+
template <class T>
- inline void iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+ inline void issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler);
template <class T>
- inline void iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level);
+ inline void issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler);
+ /**
+ * Issue the RenderNode's operations into a handler, recursing for subtrees through
+ * DrawDisplayListOp's defer() or replay() methods
+ */
template <class T>
- inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
+ inline void issueOperations(OpenGLRenderer& renderer, T& handler);
class TextContainer {
public:
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 5562f34..13a3e8e 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -31,9 +31,9 @@ void ResourceCache::logCache() {
ALOGD("ResourceCache: cacheReport:");
for (size_t i = 0; i < mCache->size(); ++i) {
ResourceReference* ref = mCache->valueAt(i);
- ALOGD(" ResourceCache: mCache(%d): resource, ref = 0x%p, 0x%p",
+ ALOGD(" ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p",
i, mCache->keyAt(i), mCache->valueAt(i));
- ALOGD(" ResourceCache: mCache(%d): refCount, recycled, destroyed, type = %d, %d, %d, %d",
+ ALOGD(" ResourceCache: mCache(%zu): refCount, recycled, destroyed, type = %d, %d, %d, %d",
i, ref->refCount, ref->recycled, ref->destroyed, ref->resourceType);
}
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index b3b4173..8ebffc2 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -392,8 +392,6 @@ void CanvasContext::drawDisplayList(RenderNode* displayList, Rect* dirty) {
LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
"drawDisplayList called on a context with no canvas or surface!");
- displayList->updateProperties();
-
EGLint width, height;
mGlobalContext->beginFrame(mEglSurface, &width, &height);
if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
new file mode 100644
index 0000000..1e9089a
--- /dev/null
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2014 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 ATRACE_TAG ATRACE_TAG_VIEW
+
+#include "DrawFrameTask.h"
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "../DisplayList.h"
+#include "../RenderNode.h"
+#include "CanvasContext.h"
+#include "RenderThread.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+DrawFrameTask::DrawFrameTask() : mContext(0), mRenderNode(0) {
+}
+
+DrawFrameTask::~DrawFrameTask() {
+}
+
+void DrawFrameTask::setContext(CanvasContext* context) {
+ mContext = context;
+}
+
+void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
+ SetDisplayListData setter;
+ setter.targetNode = renderNode;
+ setter.newData = newData;
+ mDisplayListDataUpdates.push(setter);
+}
+
+void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) {
+ mLayers.push(layer);
+}
+
+void DrawFrameTask::removeLayer(DeferredLayerUpdater* layer) {
+ for (size_t i = 0; i < mLayers.size(); i++) {
+ if (mLayers[i] == layer) {
+ mLayers.removeAt(i);
+ break;
+ }
+ }
+}
+
+void DrawFrameTask::setRenderNode(RenderNode* renderNode) {
+ mRenderNode = renderNode;
+}
+
+void DrawFrameTask::setDirty(int left, int top, int right, int bottom) {
+ mDirty.set(left, top, right, bottom);
+}
+
+void DrawFrameTask::drawFrame(RenderThread* renderThread) {
+ LOG_ALWAYS_FATAL_IF(!mRenderNode, "Cannot drawFrame with no render node!");
+ LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
+
+ AutoMutex _lock(mLock);
+ renderThread->queue(this);
+ mSignal.wait(mLock);
+
+ // Reset the single-frame data
+ mDirty.setEmpty();
+ mRenderNode = 0;
+}
+
+void DrawFrameTask::run() {
+ ATRACE_NAME("DrawFrame");
+
+ syncFrameState();
+
+ // Grab a copy of everything we need
+ Rect dirtyCopy(mDirty);
+ RenderNode* renderNode = mRenderNode;
+ CanvasContext* context = mContext;
+
+ // This is temporary until WebView has a solution for syncing frame state
+ bool canUnblockUiThread = !requiresSynchronousDraw(renderNode);
+
+ // From this point on anything in "this" is *UNSAFE TO ACCESS*
+ if (canUnblockUiThread) {
+ unblockUiThread();
+ }
+
+ drawRenderNode(context, renderNode, &dirtyCopy);
+
+ if (!canUnblockUiThread) {
+ unblockUiThread();
+ }
+}
+
+void DrawFrameTask::syncFrameState() {
+ ATRACE_CALL();
+
+ for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) {
+ const SetDisplayListData& setter = mDisplayListDataUpdates[i];
+ setter.targetNode->setData(setter.newData);
+ }
+ mDisplayListDataUpdates.clear();
+
+ mContext->processLayerUpdates(&mLayers);
+ mRenderNode->updateProperties();
+}
+
+void DrawFrameTask::unblockUiThread() {
+ AutoMutex _lock(mLock);
+ mSignal.signal();
+}
+
+void DrawFrameTask::drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty) {
+ ATRACE_CALL();
+
+ if (dirty->bottom == -1 && dirty->left == -1
+ && dirty->top == -1 && dirty->right == -1) {
+ dirty = 0;
+ }
+ context->drawDisplayList(renderNode, dirty);
+}
+
+bool DrawFrameTask::requiresSynchronousDraw(RenderNode* renderNode) {
+ return renderNode->hasFunctors();
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
new file mode 100644
index 0000000..5450dd5
--- /dev/null
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2014 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 DRAWFRAMETASK_H
+#define DRAWFRAMETASK_H
+
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/Vector.h>
+
+#include "RenderTask.h"
+
+#include "../Rect.h"
+
+namespace android {
+namespace uirenderer {
+
+class DeferredLayerUpdater;
+class DisplayListData;
+class RenderNode;
+
+namespace renderthread {
+
+class CanvasContext;
+class RenderThread;
+
+struct SetDisplayListData {
+ RenderNode* targetNode;
+ DisplayListData* newData;
+};
+
+/*
+ * This is a special Super Task. It is re-used multiple times by RenderProxy,
+ * and contains state (such as layer updaters & new DisplayListDatas) that is
+ * tracked across many frames not just a single frame.
+ * It is the sync-state task, and will kick off the post-sync draw
+ */
+class DrawFrameTask : public RenderTask {
+public:
+ DrawFrameTask();
+ virtual ~DrawFrameTask();
+
+ void setContext(CanvasContext* context);
+
+ void setDisplayListData(RenderNode* renderNode, DisplayListData* newData);
+ void addLayer(DeferredLayerUpdater* layer);
+ void removeLayer(DeferredLayerUpdater* layer);
+
+ void setRenderNode(RenderNode* renderNode);
+ void setDirty(int left, int top, int right, int bottom);
+ void drawFrame(RenderThread* renderThread);
+
+ virtual void run();
+
+private:
+ void syncFrameState();
+ void unblockUiThread();
+ static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty);
+
+ // This checks to see if there are any drawGlFunctors which would require
+ // a synchronous drawRenderNode()
+ static bool requiresSynchronousDraw(RenderNode* renderNode);
+
+ Mutex mLock;
+ Condition mSignal;
+
+ CanvasContext* mContext;
+
+ /*********************************************
+ * Single frame data
+ *********************************************/
+ RenderNode* mRenderNode;
+ Rect mDirty;
+ Vector<SetDisplayListData> mDisplayListDataUpdates;
+
+ /*********************************************
+ * Multi frame data
+ *********************************************/
+ Vector<DeferredLayerUpdater*> mLayers;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* DRAWFRAMETASK_H */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 93360fc..16b93c3 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -61,6 +61,7 @@ RenderProxy::RenderProxy(bool translucent)
SETUP_TASK(createContext);
args->translucent = translucent;
mContext = (CanvasContext*) postAndWait(task);
+ mDrawFrameTask.setContext(mContext);
}
RenderProxy::~RenderProxy() {
@@ -77,7 +78,10 @@ void RenderProxy::destroyContext() {
SETUP_TASK(destroyContext);
args->context = mContext;
mContext = 0;
- post(task);
+ mDrawFrameTask.setContext(0);
+ // This is also a fence as we need to be certain that there are no
+ // outstanding mDrawFrame tasks posted before it is destroyed
+ postAndWait(task);
}
}
@@ -117,41 +121,15 @@ void RenderProxy::setup(int width, int height) {
post(task);
}
-CREATE_BRIDGE3(setDisplayListData, CanvasContext* context, RenderNode* displayList,
- DisplayListData* newData) {
- args->context->setDisplayListData(args->displayList, args->newData);
- return NULL;
-}
-
-void RenderProxy::setDisplayListData(RenderNode* displayList, DisplayListData* newData) {
- SETUP_TASK(setDisplayListData);
- args->context = mContext;
- args->displayList = displayList;
- args->newData = newData;
- post(task);
-}
-
-CREATE_BRIDGE4(drawDisplayList, CanvasContext* context, RenderNode* displayList,
- Rect dirty, const Vector<DeferredLayerUpdater*>* layerUpdates) {
- Rect* dirty = &args->dirty;
- if (dirty->bottom == -1 && dirty->left == -1 &&
- dirty->top == -1 && dirty->right == -1) {
- dirty = 0;
- }
- args->context->processLayerUpdates(args->layerUpdates);
- args->context->drawDisplayList(args->displayList, dirty);
- return NULL;
+void RenderProxy::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
+ mDrawFrameTask.setDisplayListData(renderNode, newData);
}
void RenderProxy::drawDisplayList(RenderNode* displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
- SETUP_TASK(drawDisplayList);
- args->context = mContext;
- args->displayList = displayList;
- args->dirty.set(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
- args->layerUpdates = &mLayers;
- // TODO: Switch to post() once some form of thread safety strategy is in place
- postAndWait(task);
+ mDrawFrameTask.setRenderNode(displayList);
+ mDrawFrameTask.setDirty(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
+ mDrawFrameTask.drawFrame(&mRenderThread);
}
CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) {
@@ -205,9 +183,7 @@ CREATE_BRIDGE2(createDisplayListLayer, int width, int height) {
Layer* layer = LayerRenderer::createRenderLayer(args->width, args->height);
if (!layer) return 0;
- OpenGLRenderer* renderer = new LayerRenderer(layer);
- renderer->initProperties();
- return new DeferredLayerUpdater(layer, renderer);
+ return new DeferredLayerUpdater(layer);
}
DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) {
@@ -216,7 +192,7 @@ DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height)
args->height = height;
void* retval = postAndWait(task);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
- mLayers.push(layer);
+ mDrawFrameTask.addLayer(layer);
return layer;
}
@@ -230,7 +206,7 @@ DeferredLayerUpdater* RenderProxy::createTextureLayer() {
SETUP_TASK(createTextureLayer);
void* retval = postAndWait(task);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
- mLayers.push(layer);
+ mDrawFrameTask.addLayer(layer);
return layer;
}
@@ -254,12 +230,7 @@ bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
}
void RenderProxy::destroyLayer(DeferredLayerUpdater* layer) {
- for (size_t i = 0; i < mLayers.size(); i++) {
- if (mLayers[i] == layer) {
- mLayers.removeAt(i);
- break;
- }
- }
+ mDrawFrameTask.removeLayer(layer);
SETUP_TASK(destroyLayer);
args->layer = layer->detachBackingLayer();
post(task);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 73e9805..ee7a4c7 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -28,6 +28,8 @@
#include <utils/StrongPointer.h>
#include <utils/Vector.h>
+#include "DrawFrameTask.h"
+
namespace android {
namespace uirenderer {
@@ -60,7 +62,7 @@ public:
ANDROID_API bool initialize(EGLNativeWindowType window);
ANDROID_API void updateSurface(EGLNativeWindowType window);
ANDROID_API void setup(int width, int height);
- ANDROID_API void setDisplayListData(RenderNode* displayList, DisplayListData* newData);
+ ANDROID_API void setDisplayListData(RenderNode* renderNode, DisplayListData* newData);
ANDROID_API void drawDisplayList(RenderNode* displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
ANDROID_API void destroyCanvas();
@@ -79,11 +81,11 @@ private:
RenderThread& mRenderThread;
CanvasContext* mContext;
+ DrawFrameTask mDrawFrameTask;
+
Mutex mSyncMutex;
Condition mSyncCondition;
- Vector<DeferredLayerUpdater*> mLayers;
-
void destroyContext();
MethodInvokeRenderTask* createTask(RunnableMethod method);
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
index 06b477f..57c0320 100644
--- a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
+++ b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
@@ -32,7 +32,7 @@
struct usb_device *sDevice = NULL;
static void* read_thread(void* arg) {
- int endpoint = (int)arg;
+ int endpoint = (int)(uintptr_t)arg;
int ret = 0;
while (sDevice && ret >= 0) {
@@ -52,7 +52,7 @@ static void* read_thread(void* arg) {
}
static void* write_thread(void* arg) {
- int endpoint = (int)arg;
+ int endpoint = (int)(uintptr_t)arg;
int ret = 0;
while (ret >= 0) {
@@ -136,11 +136,11 @@ static int usb_device_added(const char *devname, void* client_data) {
}
if ((ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
- pthread_create(&th, NULL, read_thread, (void *)ep1->bEndpointAddress);
- pthread_create(&th, NULL, write_thread, (void *)ep2->bEndpointAddress);
+ pthread_create(&th, NULL, read_thread, (void *)(uintptr_t)ep1->bEndpointAddress);
+ pthread_create(&th, NULL, write_thread, (void *)(uintptr_t)ep2->bEndpointAddress);
} else {
- pthread_create(&th, NULL, read_thread, (void *)ep2->bEndpointAddress);
- pthread_create(&th, NULL, write_thread, (void *)ep1->bEndpointAddress);
+ pthread_create(&th, NULL, read_thread, (void *)(uintptr_t)ep2->bEndpointAddress);
+ pthread_create(&th, NULL, write_thread, (void *)(uintptr_t)ep1->bEndpointAddress);
}
} else {
printf("Found possible android device - attempting to switch to accessory mode\n");
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 15ae238..fce3fd0 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -202,12 +202,17 @@ public class MtpDatabase {
public void setServer(MtpServer server) {
mServer = server;
+ // always unregister before registering
+ try {
+ mContext.unregisterReceiver(mBatteryReceiver);
+ } catch (IllegalArgumentException e) {
+ // wasn't previously registered, ignore
+ }
+
// register for battery notifications when we are connected
if (server != null) {
mContext.registerReceiver(mBatteryReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- } else {
- mContext.unregisterReceiver(mBatteryReceiver);
}
}
diff --git a/media/tests/omxjpegdecoder/Android.mk b/media/tests/omxjpegdecoder/Android.mk
index 95ae33b..b0bc5d4 100644
--- a/media/tests/omxjpegdecoder/Android.mk
+++ b/media/tests/omxjpegdecoder/Android.mk
@@ -19,7 +19,6 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
omx_jpeg_decoder.cpp \
jpeg_decoder_bench.cpp \
- SkOmxPixelRef.cpp \
StreamSource.cpp
LOCAL_SHARED_LIBRARIES := \
diff --git a/media/tests/omxjpegdecoder/SkOmxPixelRef.cpp b/media/tests/omxjpegdecoder/SkOmxPixelRef.cpp
deleted file mode 100644
index a25e854..0000000
--- a/media/tests/omxjpegdecoder/SkOmxPixelRef.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <SkBitmap.h>
-
-#include "SkOmxPixelRef.h"
-
-using namespace android;
-
-SkOmxPixelRef::SkOmxPixelRef(SkColorTable* ctable, MediaBuffer* buffer,
- sp<MediaSource> decoder) {
- mBuffer = buffer;
- mDecoder = decoder;
- mSize = buffer->size();
- mCTable = ctable;
- SkSafeRef(mCTable);
-}
-
-SkOmxPixelRef::~SkOmxPixelRef() {
- mBuffer->release();
- CHECK_EQ(mDecoder->stop(), (status_t)OK);
- SkSafeUnref(mCTable);
-}
-
-void* SkOmxPixelRef::onLockPixels(SkColorTable** ct) {
- *ct = mCTable;
- return mBuffer->data();
-}
-
-void SkOmxPixelRef::onUnlockPixels() {
- // nothing to do
-}
diff --git a/media/tests/omxjpegdecoder/SkOmxPixelRef.h b/media/tests/omxjpegdecoder/SkOmxPixelRef.h
deleted file mode 100644
index 374604c..0000000
--- a/media/tests/omxjpegdecoder/SkOmxPixelRef.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SKOMXPIXELREF_DEFINED
-#define SKOMXPIXELREF_DEFINED
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
-#include <SkPixelRef.h>
-
-namespace android {
-
-class SkOmxPixelRef : public SkPixelRef {
-public:
- SkOmxPixelRef(SkColorTable* ctable, MediaBuffer* buffer,
- sp<MediaSource> decoder);
- virtual ~SkOmxPixelRef();
-
- //! Return the allocation size for the pixels
- size_t getSize() const { return mSize; }
-
- SK_DECLARE_UNFLATTENABLE_OBJECT()
-protected:
- // overrides from SkPixelRef
- virtual void* onLockPixels(SkColorTable**);
- virtual void onUnlockPixels();
-
-private:
- MediaBuffer* mBuffer;
- sp<MediaSource> mDecoder;
- size_t mSize;
- SkColorTable* mCTable;
-
- typedef SkPixelRef INHERITED;
-};
-
-} // namespace android
-#endif // SKOMXPIXELREF_DEFINED
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
index 53f04bc..3dd988e 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
@@ -34,7 +34,6 @@
#include <SkMallocPixelRef.h>
#include "omx_jpeg_decoder.h"
-#include "SkOmxPixelRef.h"
#include "StreamSource.h"
using namespace android;
@@ -158,10 +157,6 @@ bool OmxJpegImageDecoder::decodeSource(sp<MediaSource> decoder,
printf("Duration in decoder->read(): %.1f (msecs). \n",
duration / 1E3 );
- /* Mark the code for now, since we attend to copy buffer to SkBitmap.
- // Install pixelRef to Bitmap.
- installPixelRef(buffer, decoder, bm);*/
-
// Copy pixels from buffer to bm.
// May need to check buffer->rawBytes() == bm->rawBytes().
CHECK_EQ(buffer->size(), bm->getSize());
@@ -172,17 +167,6 @@ bool OmxJpegImageDecoder::decodeSource(sp<MediaSource> decoder,
return true;
}
-void OmxJpegImageDecoder::installPixelRef(MediaBuffer *buffer, sp<MediaSource> decoder,
- SkBitmap* bm) {
-
- // set bm's pixelref based on the data in buffer.
- SkAutoLockPixels alp(*bm);
- SkPixelRef* pr = new SkOmxPixelRef(NULL, buffer, decoder);
- bm->setPixelRef(pr)->unref();
- bm->lockPixels();
- return;
-}
-
void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkBitmap::Config pref,
int width, int height) {
bm->setConfig(getColorSpaceConfig(pref), width, height, 0, kOpaque_SkAlphaType);
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
index a313877..e431e72 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
@@ -49,8 +49,6 @@ private:
sp<MediaSource> getDecoder(OMXClient* client, const sp<MediaSource>& source);
bool decodeSource(sp<MediaSource> decoder, const sp<MediaSource>& source,
SkBitmap* bm);
- void installPixelRef(MediaBuffer* buffer, sp<MediaSource> decoder,
- SkBitmap* bm);
void configBitmapSize(SkBitmap* bm, SkBitmap::Config pref, int width,
int height);
SkBitmap::Config getColorSpaceConfig(SkBitmap::Config pref);
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 1693e01..1da66bb 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -92,6 +92,12 @@
systemui:rowHeight="@dimen/notification_row_min_height"
/>
</ScrollView>
+
+ <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+ android:id="@+id/notification_stack_scroller"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ />
</FrameLayout>
</LinearLayout>
</com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d7457f0..2e116d0 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7164937344850004466">"የስርዓት UI"</string>
- <string name="status_bar_clear_all_button" msgid="7774721344716731603">"አጥራ"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"አጽዳ"</string>
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"ከዝርዝር አስወግድ"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"የትግበራ መረጃ"</string>
<string name="status_bar_no_recent_apps" msgid="6576392951053994640">"ምንም የቅርብ ጊዜ ትግበራዎች የሉም"</string>
@@ -136,7 +136,7 @@
<string name="accessibility_battery_level" msgid="7451474187113371965">"የባትሪ <xliff:g id="NUMBER">%d</xliff:g> መቶኛ።"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"የስርዓት ቅንብሮች"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"ማሳወቂያዎች"</string>
- <string name="accessibility_remove_notification" msgid="3603099514902182350">"ማሳወቂያ አጥራ"</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"ማሳወቂያ አጽዳ"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ነቅቷል።"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS በማግኘት ላይ።"</string>
<string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter ነቅቷል።"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 7671ef1..289d6c6 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -188,8 +188,8 @@
<string name="quick_settings_rotation_locked_portrait_label" msgid="1553131290066230775">"Bloccato in verticale"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="7216265671276086593">"Bloccato in orizzontale"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Metodo di immissione"</string>
- <string name="quick_settings_location_label" msgid="5011327048748762257">"Geolocalizzazione"</string>
- <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Posizione non attiva"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Geolocalizz."</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Geolocalizz. non attiva"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositivo multimediale"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Solo chiamate di emergenza"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index a59dc75..5cf0453 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -39,8 +39,6 @@
<color name="status_bar_clock_color">#FFFFFFFF</color>
<drawable name="notification_item_background_color">#ff111111</drawable>
<drawable name="notification_item_background_color_pressed">#ff454545</drawable>
- <color name="notification_icon_legacy_bg_color">#ff4285F4</color>
- <color name="notification_action_legacy_color_filter">#ff555555</color>
<!-- Tint color for inactive Quick Settings icons. -->
<color name="ic_qs_off">#ff404040</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1dd9300..77ab17b 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -56,10 +56,10 @@
<!-- Amount of time to hold off before showing the search panel when the user presses home -->
<integer name="config_show_search_delay">200</integer>
- <!-- Vibration duration for MultiWaveView used in SearchPanelView -->
+ <!-- Vibration duration for GlowPadView used in SearchPanelView -->
<integer translatable="false" name="config_vibration_duration">0</integer>
- <!-- Vibration duration for MultiWaveView used in SearchPanelView -->
+ <!-- Vibration duration for GlowPadView used in SearchPanelView -->
<integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
<!-- The length of the vibration when the notification pops open. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e67e8cf..a9b6985 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -233,6 +233,21 @@
<!-- The size of the icon in the recents task view. -->
<dimen name="recents_task_view_icon_size">60dp</dimen>
+ <!-- Space below the notification stack -->
+ <dimen name="notification_stack_margin_bottom">0dp</dimen>
+
+ <!-- Space reserved for the cards behind the top card in the top stack -->
+ <dimen name="top_stack_peek_amount">24dp</dimen>
+
+ <!-- Space reserved for the cards behind the top card in the bottom stack -->
+ <dimen name="bottom_stack_peek_amount">18dp</dimen>
+
+ <!-- The side padding of the notifications-->
+ <dimen name="notification_side_padding">8dp</dimen>
+
+ <!-- Z distance between notifications if they are in the stack -->
+ <dimen name="z_distance_between_notifications">2dp</dimen>
+
<!-- Width of the zen mode interstitial dialog. Defaults to MATCH_PARENT. -->
<dimen name="zen_mode_dialog_width">-1px</dimen>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 48a6522..b85d5b9 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -108,7 +108,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
private int mGravity;
- private View mScrollView;
+ private ScrollAdapter mScrollAdapter;
private OnScaleGestureListener mScaleGestureListener
= new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@@ -301,8 +301,8 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
mGravity = gravity;
}
- public void setScrollView(View scrollView) {
- mScrollView = scrollView;
+ public void setScrollAdapter(ScrollAdapter adapter) {
+ mScrollAdapter = adapter;
}
private float calculateGlow(float target, float actual) {
@@ -384,7 +384,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
}
return true;
}
- if (mScrollView != null && mScrollView.getScrollY() > 0) {
+ if (mScrollAdapter != null && !mScrollAdapter.isScrolledToTop()) {
return false;
}
// Now look for other gestures
@@ -407,7 +407,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
}
case MotionEvent.ACTION_DOWN:
- mWatchingForPull = isInside(mScrollView, x, y);
+ mWatchingForPull = isInside(mScrollAdapter.getHostView(), x, y);
mLastMotionY = y;
break;
@@ -608,5 +608,19 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
}
mVibrator.vibrate(duration, AudioManager.STREAM_SYSTEM);
}
+
+ public interface ScrollAdapter {
+
+ /**
+ * @return Whether the view returned by {@link #getHostView()} is scrolled to the top
+ * and can therefore be expanded by a single finger drag
+ */
+ public boolean isScrolledToTop();
+
+ /**
+ * @return The view in which the scrolling is performed
+ */
+ public View getHostView();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 117ae81..bad5641 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -29,14 +29,9 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.database.ContentObserver;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
import android.graphics.Rect;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
@@ -46,20 +41,17 @@ import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.service.notification.StatusBarNotification;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
import android.text.TextUtils;
-import android.text.style.TextAppearanceSpan;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
-import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.IWindowManager;
import android.view.LayoutInflater;
@@ -70,7 +62,6 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
-import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
@@ -80,18 +71,16 @@ import android.widget.TextView;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.util.LegacyNotificationUtil;
import com.android.internal.widget.SizeAdaptiveLayout;
-import com.android.systemui.ImageUtils;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SearchPanelView;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
-import com.android.systemui.statusbar.policy.NotificationRowLayout;
import java.util.ArrayList;
import java.util.Locale;
-import java.util.Stack;
public abstract class BaseStatusBar extends SystemUI implements
CommandQueue.Callbacks {
@@ -109,6 +98,8 @@ public abstract class BaseStatusBar extends SystemUI implements
protected static final int MSG_HIDE_HEADS_UP = 1027;
protected static final int MSG_ESCALATE_HEADS_UP = 1028;
+ public static final boolean ENABLE_NOTIFICATION_STACK = SystemProperties
+ .getBoolean("persist.notifications.use_stack", false);
protected static final boolean ENABLE_HEADS_UP = true;
// scores above this threshold should be displayed in heads up mode.
protected static final int INTERRUPTION_THRESHOLD = 10;
@@ -129,7 +120,7 @@ public abstract class BaseStatusBar extends SystemUI implements
// all notifications
protected NotificationData mNotificationData = new NotificationData();
- protected NotificationRowLayout mPile;
+ protected ViewGroup mPile;
protected NotificationData.Entry mInterruptingNotificationEntry;
protected long mInterruptingNotificationTime;
@@ -157,8 +148,7 @@ public abstract class BaseStatusBar extends SystemUI implements
// public mode, private notifications, etc
private boolean mLockscreenPublicMode = false;
private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
- private Context mLightThemeContext;
- private ImageUtils mImageUtils = new ImageUtils();
+ private LegacyNotificationUtil mLegacyNotificationUtil = LegacyNotificationUtil.getInstance();
private UserManager mUserManager;
@@ -296,8 +286,6 @@ public abstract class BaseStatusBar extends SystemUI implements
true,
mLockscreenSettingsObserver,
UserHandle.USER_ALL);
- mLightThemeContext = new RemoteViewsThemeContextWrapper(mContext,
- android.R.style.Theme_Holo_Light);
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -458,158 +446,6 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
- private void processLegacyHoloNotification(StatusBarNotification sbn, View content) {
-
- // TODO: Also skip processing if it is a holo-style notification.
- // If the notification is custom, we can't process it.
- if (!sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) {
- return;
- }
-
- processLegacyHoloLargeIcon(content);
- processLegacyHoloActions(content);
- processLegacyNotificationIcon(content);
- processLegacyTextViews(content);
- }
-
- /**
- * @return the context to be used for the inflation of the specified {@code sbn}; this is
- * dependent whether the notification is quantum-style or holo-style
- */
- private Context getInflationContext(StatusBarNotification sbn) {
-
- // TODO: Adjust this logic when we change the theme of the status bar windows.
- if (sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) {
- return mLightThemeContext;
- } else {
- return mContext;
- }
- }
-
- private void processLegacyNotificationIcon(View content) {
- View v = content.findViewById(com.android.internal.R.id.right_icon);
- if (v != null & v instanceof ImageView) {
- ImageView iv = (ImageView) v;
- Drawable d = iv.getDrawable();
- if (isMonochrome(d)) {
- d.mutate();
- d.setColorFilter(mLightThemeContext.getResources().getColor(
- R.color.notification_action_legacy_color_filter), PorterDuff.Mode.MULTIPLY);
- }
- }
- }
-
- private void processLegacyHoloLargeIcon(View content) {
- View v = content.findViewById(com.android.internal.R.id.icon);
- if (v != null & v instanceof ImageView) {
- ImageView iv = (ImageView) v;
- if (isMonochrome(iv.getDrawable())) {
- iv.setBackground(mLightThemeContext.getResources().getDrawable(
- R.drawable.notification_icon_legacy_bg_inset));
- }
- }
- }
-
- private boolean isMonochrome(Drawable d) {
- if (d == null) {
- return false;
- } else if (d instanceof BitmapDrawable) {
- BitmapDrawable bd = (BitmapDrawable) d;
- return bd.getBitmap() != null && mImageUtils.isGrayscale(bd.getBitmap());
- } else if (d instanceof AnimationDrawable) {
- AnimationDrawable ad = (AnimationDrawable) d;
- int count = ad.getNumberOfFrames();
- return count > 0 && isMonochrome(ad.getFrame(0));
- } else {
- return false;
- }
- }
-
- private void processLegacyHoloActions(View content) {
- View v = content.findViewById(com.android.internal.R.id.actions);
- if (v != null & v instanceof ViewGroup) {
- ViewGroup vg = (ViewGroup) v;
- int childCount = vg.getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = vg.getChildAt(i);
- if (child instanceof Button) {
- Button button = (Button) child;
- Drawable[] compoundDrawables = button.getCompoundDrawablesRelative();
- if (isMonochrome(compoundDrawables[0])) {
- Drawable d = compoundDrawables[0];
- d.mutate();
- d.setColorFilter(mLightThemeContext.getResources().getColor(
- R.color.notification_action_legacy_color_filter),
- PorterDuff.Mode.MULTIPLY);
- }
- }
- }
- }
- }
-
- private void processLegacyTextViews(View content) {
- Stack<View> viewStack = new Stack<View>();
- viewStack.push(content);
- while(!viewStack.isEmpty()) {
- View current = viewStack.pop();
- if(current instanceof ViewGroup){
- ViewGroup currentGroup = (ViewGroup) current;
- int numChildren = currentGroup.getChildCount();
- for(int i=0;i<numChildren;i++){
- viewStack.push(currentGroup.getChildAt(i));
- }
- }
- if (current instanceof TextView) {
- processLegacyTextView((TextView) current);
- }
- }
- }
-
- private void processLegacyTextView(TextView textView) {
- if (textView.getText() instanceof Spanned) {
- Spanned ss = (Spanned) textView.getText();
- Object[] spans = ss.getSpans(0, ss.length(), Object.class);
- SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
- for (Object span : spans) {
- Object resultSpan = span;
- if (span instanceof TextAppearanceSpan) {
- resultSpan = processTextAppearanceSpan((TextAppearanceSpan) span);
- }
- builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
- ss.getSpanFlags(span));
- }
- textView.setText(builder);
- }
- }
-
- private TextAppearanceSpan processTextAppearanceSpan(TextAppearanceSpan span) {
- ColorStateList colorStateList = span.getTextColor();
- if (colorStateList != null) {
- int[] colors = colorStateList.getColors();
- boolean changed = false;
- for (int i = 0; i < colors.length; i++) {
- if (mImageUtils.isGrayscale(colors[i])) {
- colors[i] = processColor(colors[i]);
- changed = true;
- }
- }
- if (changed) {
- return new TextAppearanceSpan(
- span.getFamily(), span.getTextStyle(), span.getTextSize(),
- new ColorStateList(colorStateList.getStates(), colors),
- span.getLinkTextColor());
- }
- }
- return span;
- }
-
- private int processColor(int color) {
- return Color.argb(Color.alpha(color),
- 255 - Color.red(color),
- 255 - Color.green(color),
- 255 - Color.blue(color));
- }
-
private void startApplicationDetailsActivity(String packageName) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null));
@@ -947,10 +783,10 @@ public abstract class BaseStatusBar extends SystemUI implements
View contentViewLocal = null;
View bigContentViewLocal = null;
try {
- contentViewLocal = contentView.apply(getInflationContext(sbn), expanded,
+ contentViewLocal = contentView.apply(mContext, expanded,
mOnClickHandler);
if (bigContentView != null) {
- bigContentViewLocal = bigContentView.apply(getInflationContext(sbn), expanded,
+ bigContentViewLocal = bigContentView.apply(mContext, expanded,
mOnClickHandler);
}
}
@@ -983,8 +819,8 @@ public abstract class BaseStatusBar extends SystemUI implements
View publicViewLocal = null;
if (publicNotification != null) {
try {
- publicViewLocal = publicNotification.contentView.apply(getInflationContext(sbn),
- expandedPublic, mOnClickHandler);
+ publicViewLocal = publicNotification.contentView.apply(mContext, expandedPublic,
+ mOnClickHandler);
if (publicViewLocal != null) {
publicViewLocal.setIsRootNamespace(true);
@@ -1005,7 +841,8 @@ public abstract class BaseStatusBar extends SystemUI implements
if (publicViewLocal == null) {
// Add a basic notification template
publicViewLocal = LayoutInflater.from(mContext).inflate(
- com.android.internal.R.layout.notification_template_base, expandedPublic, true);
+ com.android.internal.R.layout.notification_template_quantum_base,
+ expandedPublic, true);
final TextView title = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.title);
try {
@@ -1024,7 +861,12 @@ public abstract class BaseStatusBar extends SystemUI implements
entry.notification.getNotification().number,
entry.notification.getNotification().tickerText);
- icon.setImageDrawable(StatusBarIconView.getIcon(mContext, ic));
+ Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic);
+ icon.setImageDrawable(iconDrawable);
+ if (mLegacyNotificationUtil.isGrayscale(iconDrawable)) {
+ icon.setBackgroundResource(
+ com.android.internal.R.drawable.notification_icon_legacy_bg_inset);
+ }
final TextView text = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.text);
text.setText("Unlock your device to see this notification.");
@@ -1035,13 +877,6 @@ public abstract class BaseStatusBar extends SystemUI implements
row.setDrawingCacheEnabled(true);
applyLegacyRowBackground(sbn, content);
- processLegacyHoloNotification(sbn, contentViewLocal);
- if (bigContentViewLocal != null) {
- processLegacyHoloNotification(sbn, bigContentViewLocal);
- }
- if (publicViewLocal != null) {
- processLegacyHoloNotification(sbn, publicViewLocal);
- }
if (MULTIUSER_DEBUG) {
TextView debug = (TextView) row.findViewById(R.id.debug_info);
@@ -1458,17 +1293,13 @@ public abstract class BaseStatusBar extends SystemUI implements
: null;
// Reapply the RemoteViews
- contentView.reapply(getInflationContext(notification), entry.expanded, mOnClickHandler);
- processLegacyHoloNotification(notification, entry.expanded);
+ contentView.reapply(mContext, entry.expanded, mOnClickHandler);
if (bigContentView != null && entry.getBigContentView() != null) {
- bigContentView.reapply(getInflationContext(notification), entry.getBigContentView(),
+ bigContentView.reapply(mContext, entry.getBigContentView(),
mOnClickHandler);
- processLegacyHoloNotification(notification, entry.getBigContentView());
}
if (publicContentView != null && entry.getPublicContentView() != null) {
- publicContentView.reapply(getInflationContext(notification),
- entry.getPublicContentView(), mOnClickHandler);
- processLegacyHoloNotification(notification, entry.getPublicContentView());
+ publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler);
}
// update the contentIntent
final PendingIntent contentIntent = notification.getNotification().contentIntent;
@@ -1539,35 +1370,4 @@ public abstract class BaseStatusBar extends SystemUI implements
}
mContext.unregisterReceiver(mBroadcastReceiver);
}
-
- /**
- * A custom context theme wrapper that applies a platform theme to a created package context.
- * This is useful if you want to inflate {@link RemoteViews} with a custom theme (normally, the
- * theme used there is the default platform theme).
- */
- private static class RemoteViewsThemeContextWrapper extends ContextThemeWrapper {
-
- private int mThemeRes;
-
- private RemoteViewsThemeContextWrapper(Context base, int themeres) {
- super(base, themeres);
- mThemeRes = themeres;
- }
-
- @Override
- public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
- throws NameNotFoundException {
- Context c = super.createPackageContextAsUser(packageName, flags, user);
- c.setTheme(mThemeRes);
- return c;
- }
-
- @Override
- public Context createPackageContext(String packageName, int flags)
- throws NameNotFoundException {
- Context c = super.createPackageContext(packageName, flags);
- c.setTheme(mThemeRes);
- return c;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 650c557..e7f96dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -80,13 +80,13 @@ import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.ScrollView;
import android.widget.TextView;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.DemoMode;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.GestureRecorder;
@@ -94,6 +94,7 @@ import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
+
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.DateView;
@@ -104,6 +105,8 @@ import com.android.systemui.statusbar.policy.NotificationRowLayout;
import com.android.systemui.statusbar.policy.OnSizeChangedListener;
import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -195,7 +198,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
// expanded notifications
NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
- ScrollView mScrollView;
+ View mNotificationScroller;
View mExpandedContents;
int mNotificationPanelGravity;
int mNotificationPanelMarginBottomPx, mNotificationPanelMarginPx;
@@ -479,11 +482,34 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
mTickerView = mStatusBarView.findViewById(R.id.ticker);
- mPile = (NotificationRowLayout)mStatusBarWindow.findViewById(R.id.latestItems);
- mPile.setLayoutTransitionsEnabled(false);
- mPile.setLongPressListener(getNotificationLongClicker());
+ View legacyScrollView = mStatusBarWindow.findViewById(R.id.scroll);
+ NotificationStackScrollLayout notificationStack
+ = (NotificationStackScrollLayout) mStatusBarWindow
+ .findViewById(R.id.notification_stack_scroller);
+ if (ENABLE_NOTIFICATION_STACK) {
+ notificationStack.setLongPressListener(getNotificationLongClicker());
+ mPile = notificationStack;
+ legacyScrollView.setVisibility(View.GONE);
+
+ // The scrollview and the notification container are unified now!
+ // TODO: remove mNotificationScroller entirely once we fully switch to the new Layout
+ mNotificationScroller = notificationStack;
+ } else {
+ mNotificationScroller = legacyScrollView;
+ // less drawing during pulldowns
+ mNotificationScroller.setVerticalScrollBarEnabled(false);
+ NotificationRowLayout rowLayout
+ = (NotificationRowLayout) mStatusBarWindow.findViewById(R.id.latestItems);
+ rowLayout.setLayoutTransitionsEnabled(false);
+ rowLayout.setLongPressListener(getNotificationLongClicker());
+ mPile = rowLayout;
+ notificationStack.setVisibility(View.GONE);
+ }
+
mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
+
+
mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
@@ -531,10 +557,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
}
- mScrollView = (ScrollView)mStatusBarWindow.findViewById(R.id.scroll);
- mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns
if (!mNotificationPanelIsFullScreenWidth) {
- mScrollView.setSystemUiVisibility(
+ mNotificationPanel.setSystemUiVisibility(
View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS |
View.STATUS_BAR_DISABLE_CLOCK);
}
@@ -597,7 +621,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
// set up the dynamic hide/show of the label
- mPile.setOnSizeChangedListener(new OnSizeChangedListener() {
+ if (!ENABLE_NOTIFICATION_STACK)
+ ((NotificationRowLayout) mPile).setOnSizeChangedListener(new OnSizeChangedListener() {
@Override
public void onSizeChanged(View view, int w, int h, int oldw, int oldh) {
updateCarrierLabelVisibility(false);
@@ -1148,19 +1173,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
protected void updateCarrierLabelVisibility(boolean force) {
+ // TODO: Handle this for the notification stack scroller as well
if (!mShowCarrierInPanel) return;
// The idea here is to only show the carrier label when there is enough room to see it,
// i.e. when there aren't enough notifications to fill the panel.
if (SPEW) {
Log.d(TAG, String.format("pileh=%d scrollh=%d carrierh=%d",
- mPile.getHeight(), mScrollView.getHeight(), mCarrierLabelHeight));
+ mPile.getHeight(), mNotificationScroller.getHeight(), mCarrierLabelHeight));
}
final boolean emergencyCallsShownElsewhere = mEmergencyCallLabel != null;
final boolean makeVisible =
!(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly())
&& mPile.getHeight() < (mNotificationPanel.getHeight() - mCarrierLabelHeight - mNotificationHeaderHeight)
- && mScrollView.getVisibility() == View.VISIBLE;
+ && mNotificationScroller.getVisibility() == View.VISIBLE;
if (force || mCarrierLabelVisible != makeVisible) {
mCarrierLabelVisible = makeVisible;
@@ -1203,7 +1229,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
if (mHasFlipSettings
&& mFlipSettingsView != null
&& mFlipSettingsView.getVisibility() == View.VISIBLE
- && mScrollView.getVisibility() != View.VISIBLE) {
+ && mNotificationScroller.getVisibility() != View.VISIBLE) {
// the flip settings panel is unequivocally showing; we should not be shown
mClearButton.setVisibility(View.INVISIBLE);
} else if (mClearButton.isShown()) {
@@ -1457,7 +1483,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
mExpandedVisible = true;
- mPile.setLayoutTransitionsEnabled(true);
+ if (!ENABLE_NOTIFICATION_STACK) {
+ ((NotificationRowLayout) mPile).setLayoutTransitionsEnabled(true);
+ }
if (mNavigationBarView != null)
mNavigationBarView.setSlippery(true);
@@ -1572,7 +1600,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
mNotificationPanel.expand();
- if (mHasFlipSettings && mScrollView.getVisibility() != View.VISIBLE) {
+ if (mHasFlipSettings && mNotificationScroller.getVisibility() != View.VISIBLE) {
flipToNotifications();
}
@@ -1586,11 +1614,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
if (mClearButtonAnim != null) mClearButtonAnim.cancel();
- mScrollView.setVisibility(View.VISIBLE);
+ mNotificationScroller.setVisibility(View.VISIBLE);
mScrollViewAnim = start(
startDelay(FLIP_DURATION_OUT,
interpolator(mDecelerateInterpolator,
- ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 0f, 1f)
+ ObjectAnimator.ofFloat(mNotificationScroller, View.SCALE_X, 0f, 1f)
.setDuration(FLIP_DURATION_IN)
)));
mFlipSettingsViewAnim = start(
@@ -1648,8 +1676,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
mFlipSettingsView.setScaleX(1f);
mFlipSettingsView.setVisibility(View.VISIBLE);
mSettingsButton.setVisibility(View.GONE);
- mScrollView.setVisibility(View.GONE);
- mScrollView.setScaleX(0f);
+ mNotificationScroller.setVisibility(View.GONE);
+ mNotificationScroller.setScaleX(0f);
mNotificationButton.setVisibility(View.VISIBLE);
mNotificationButton.setAlpha(1f);
mClearButton.setVisibility(View.GONE);
@@ -1676,15 +1704,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
mScrollViewAnim = start(
setVisibilityWhenDone(
interpolator(mAccelerateInterpolator,
- ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 1f, 0f)
+ ObjectAnimator.ofFloat(mNotificationScroller, View.SCALE_X, 1f, 0f)
)
.setDuration(FLIP_DURATION_OUT),
- mScrollView, View.INVISIBLE));
+ mNotificationScroller, View.INVISIBLE));
mSettingsButtonAnim = start(
setVisibilityWhenDone(
ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
.setDuration(FLIP_DURATION),
- mScrollView, View.INVISIBLE));
+ mNotificationScroller, View.INVISIBLE));
mNotificationButton.setVisibility(View.VISIBLE);
mNotificationButtonAnim = start(
ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
@@ -1738,8 +1766,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
if (mClearButtonAnim != null) mClearButtonAnim.cancel();
- mScrollView.setScaleX(1f);
- mScrollView.setVisibility(View.VISIBLE);
+ mNotificationScroller.setScaleX(1f);
+ mNotificationScroller.setVisibility(View.VISIBLE);
mSettingsButton.setAlpha(1f);
mSettingsButton.setVisibility(View.VISIBLE);
mNotificationPanel.setVisibility(View.GONE);
@@ -1749,7 +1777,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}
mExpandedVisible = false;
- mPile.setLayoutTransitionsEnabled(false);
+ if (!ENABLE_NOTIFICATION_STACK) {
+ ((NotificationRowLayout) mPile).setLayoutTransitionsEnabled(false);
+ }
if (mNavigationBarView != null)
mNavigationBarView.setSlippery(false);
visibilityChanged(false);
@@ -2202,8 +2232,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
pw.println(" mDisplayMetrics=" + mDisplayMetrics);
pw.println(" mPile: " + viewInfo(mPile));
pw.println(" mTickerView: " + viewInfo(mTickerView));
- pw.println(" mScrollView: " + viewInfo(mScrollView)
- + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
+ pw.println(" mNotificationScroller: " + viewInfo(mNotificationScroller)
+ + " scroll " + mNotificationScroller.getScrollX()
+ + "," + mNotificationScroller.getScrollY());
}
pw.print(" mInteractingWindows="); pw.println(mInteractingWindows);
@@ -2397,17 +2428,38 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
public void onClick(View v) {
+ // TODO: Handle this better with notification stack scroller
synchronized (mNotificationData) {
+ mPostCollapseCleanup = new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG) {
+ Log.v(TAG, "running post-collapse cleanup");
+ }
+ try {
+ if (!ENABLE_NOTIFICATION_STACK) {
+ ((NotificationRowLayout) mPile).setViewRemoval(true);
+ }
+ mBarService.onClearAllNotifications(mCurrentUserId);
+ } catch (Exception ex) { }
+ }
+ };
+
+ if(ENABLE_NOTIFICATION_STACK) {
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+ return;
+ }
+
// animate-swipe all dismissable notifications, then animate the shade closed
int numChildren = mPile.getChildCount();
- int scrollTop = mScrollView.getScrollY();
- int scrollBottom = scrollTop + mScrollView.getHeight();
+ int scrollTop = mNotificationScroller.getScrollY();
+ int scrollBottom = scrollTop + mNotificationScroller.getHeight();
final ArrayList<View> snapshot = new ArrayList<View>(numChildren);
for (int i=0; i<numChildren; i++) {
final View child = mPile.getChildAt(i);
- if (mPile.canChildBeDismissed(child) && child.getBottom() > scrollTop &&
- child.getTop() < scrollBottom) {
+ if (((SwipeHelper.Callback) mPile).canChildBeDismissed(child)
+ && child.getBottom() > scrollTop && child.getTop() < scrollBottom) {
snapshot.add(child);
}
}
@@ -2424,23 +2476,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
int currentDelay = 140;
int totalDelay = 0;
- // Set the shade-animating state to avoid doing other work during
- // all of these animations. In particular, avoid layout and
- // redrawing when collapsing the shade.
- mPile.setViewRemoval(false);
- mPostCollapseCleanup = new Runnable() {
- @Override
- public void run() {
- if (DEBUG) {
- Log.v(TAG, "running post-collapse cleanup");
- }
- try {
- mPile.setViewRemoval(true);
- mBarService.onClearAllNotifications(mCurrentUserId);
- } catch (Exception ex) { }
- }
- };
+ if (!ENABLE_NOTIFICATION_STACK) {
+ // Set the shade-animating state to avoid doing other work during
+ // all of these animations. In particular, avoid layout and
+ // redrawing when collapsing the shade.
+ ((NotificationRowLayout) mPile).setViewRemoval(false);
+ }
View sampleView = snapshot.get(0);
int width = sampleView.getWidth();
@@ -2450,7 +2492,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
- mPile.dismissRowAnimated(_v, velocity);
+ if (!ENABLE_NOTIFICATION_STACK) {
+ ((NotificationRowLayout) mPile).dismissRowAnimated(
+ _v, velocity);
+ } else {
+ ((NotificationStackScrollLayout) mPile).dismissRowAnimated(
+ _v, velocity);
+ }
}
}, totalDelay);
currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 7b03195..eeae081 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -24,14 +24,14 @@ import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.widget.FrameLayout;
-import android.widget.ScrollView;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
-import com.android.systemui.statusbar.policy.NotificationRowLayout;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
public class StatusBarWindowView extends FrameLayout
@@ -40,9 +40,9 @@ public class StatusBarWindowView extends FrameLayout
public static final boolean DEBUG = BaseStatusBar.DEBUG;
private ExpandHelper mExpandHelper;
- private NotificationRowLayout latestItems;
+ private ViewGroup latestItems;
private NotificationPanelView mNotificationPanel;
- private ScrollView mScrollView;
+ private View mNotificationScroller;
PhoneStatusBar mService;
@@ -55,14 +55,38 @@ public class StatusBarWindowView extends FrameLayout
@Override
protected void onAttachedToWindow () {
super.onAttachedToWindow();
- latestItems = (NotificationRowLayout) findViewById(R.id.latestItems);
- mScrollView = (ScrollView) findViewById(R.id.scroll);
+
+ ExpandHelper.ScrollAdapter scrollAdapter;
+ if (BaseStatusBar.ENABLE_NOTIFICATION_STACK) {
+ NotificationStackScrollLayout stackScrollLayout =
+ (NotificationStackScrollLayout) findViewById(R.id.notification_stack_scroller);
+
+ // ScrollView and notification container are unified in a single view now.
+ latestItems = stackScrollLayout;
+ scrollAdapter = stackScrollLayout;
+ mNotificationScroller = stackScrollLayout;
+ } else {
+ latestItems = (ViewGroup) findViewById(R.id.latestItems);
+ mNotificationScroller = findViewById(R.id.scroll);
+ scrollAdapter = new ExpandHelper.ScrollAdapter() {
+ @Override
+ public boolean isScrolledToTop() {
+ return mNotificationScroller.getScrollY() == 0;
+ }
+
+ @Override
+ public View getHostView() {
+ return mNotificationScroller;
+ }
+ };
+ }
mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
- mExpandHelper = new ExpandHelper(getContext(), latestItems, minHeight, maxHeight);
+ mExpandHelper = new ExpandHelper(getContext(), (ExpandHelper.Callback) latestItems,
+ minHeight, maxHeight);
mExpandHelper.setEventSource(this);
- mExpandHelper.setScrollView(mScrollView);
+ mExpandHelper.setScrollAdapter(scrollAdapter);
// We really need to be able to animate while window animations are going on
// so that activities may be started asynchronously from panel animations
@@ -88,7 +112,8 @@ public class StatusBarWindowView extends FrameLayout
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
- if (mNotificationPanel.isFullyExpanded() && mScrollView.getVisibility() == View.VISIBLE) {
+ if (mNotificationPanel.isFullyExpanded()
+ && mNotificationScroller.getVisibility() == View.VISIBLE) {
intercept = mExpandHelper.onInterceptTouchEvent(ev);
}
if (!intercept) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
new file mode 100644
index 0000000..ff8ea405
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -0,0 +1,826 @@
+/*
+ * Copyright (C) 2014 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.stack;
+
+import android.content.Context;
+import android.content.res.Configuration;
+
+import android.graphics.Canvas;
+import android.graphics.Outline;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.OverScroller;
+
+import com.android.systemui.ExpandHelper;
+import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+
+/**
+ * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
+ */
+public class NotificationStackScrollLayout extends ViewGroup
+ implements SwipeHelper.Callback, ExpandHelper.Callback, ExpandHelper.ScrollAdapter {
+
+ private static final String TAG = "NotificationStackScrollLayout";
+ private static final boolean DEBUG = false;
+
+ /**
+ * Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
+ */
+ private static final int INVALID_POINTER = -1;
+
+ private SwipeHelper mSwipeHelper;
+ private boolean mAllowScrolling = true;
+ private int mCurrentStackHeight = Integer.MAX_VALUE;
+ private int mOwnScrollY;
+ private int mMaxLayoutHeight;
+
+ private VelocityTracker mVelocityTracker;
+ private OverScroller mScroller;
+ private int mTouchSlop;
+ private int mMinimumVelocity;
+ private int mMaximumVelocity;
+ private int mOverscrollDistance;
+ private int mOverflingDistance;
+ private boolean mIsBeingDragged;
+ private int mLastMotionY;
+ private int mActivePointerId;
+
+ private int mSidePaddings;
+ private Paint mDebugPaint;
+ private int mBackgroundRoundedRectCornerRadius;
+ private int mContentHeight;
+ private int mCollapsedSize;
+ private int mBottomStackPeekSize;
+ private int mEmptyMarginBottom;
+ private int mPaddingBetweenElements;
+
+ /**
+ * The algorithm which calculates the properties for our children
+ */
+ private StackScrollAlgorithm mStackScrollAlgorithm;
+
+ /**
+ * The current State this Layout is in
+ */
+ private StackScrollState mCurrentStackScrollState;
+
+ public NotificationStackScrollLayout(Context context) {
+ this(context, null);
+ }
+
+ public NotificationStackScrollLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ initView(context);
+ if (DEBUG) {
+ setWillNotDraw(false);
+ mDebugPaint = new Paint();
+ mDebugPaint.setColor(0xffff0000);
+ mDebugPaint.setStrokeWidth(2);
+ mDebugPaint.setStyle(Paint.Style.STROKE);
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (DEBUG) {
+ int y = mCollapsedSize;
+ canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+ y = (int) (getLayoutHeight() - mBottomStackPeekSize - mCollapsedSize);
+ canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+ y = (int) getLayoutHeight();
+ canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+ }
+ }
+
+ private void initView(Context context) {
+ mScroller = new OverScroller(getContext());
+ setFocusable(true);
+ setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
+ final ViewConfiguration configuration = ViewConfiguration.get(context);
+ mTouchSlop = configuration.getScaledTouchSlop();
+ mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
+ mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+ mOverscrollDistance = configuration.getScaledOverscrollDistance();
+ mOverflingDistance = configuration.getScaledOverflingDistance();
+ float densityScale = getResources().getDisplayMetrics().density;
+ float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
+
+ mSidePaddings = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_side_padding);
+ mBackgroundRoundedRectCornerRadius = context.getResources()
+ .getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_quantum_rounded_rect_radius);
+ mCollapsedSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_row_min_height);
+ mBottomStackPeekSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
+ mEmptyMarginBottom = context.getResources().getDimensionPixelSize(
+ R.dimen.notification_stack_margin_bottom);
+ // currently the padding is in the elements themself
+ mPaddingBetweenElements = 0;
+ mStackScrollAlgorithm = new StackScrollAlgorithm(context);
+ mCurrentStackScrollState = null;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int mode = MeasureSpec.getMode(widthMeasureSpec);
+ int size = MeasureSpec.getSize(widthMeasureSpec);
+ int childMeasureSpec = MeasureSpec.makeMeasureSpec(size - 2 * mSidePaddings, mode);
+ measureChildren(childMeasureSpec, heightMeasureSpec);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+
+ // we layout all our children centered on the top
+ float centerX = getWidth() / 2.0f;
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ float width = child.getMeasuredWidth();
+ float height = child.getMeasuredHeight();
+ int oldWidth = child.getWidth();
+ int oldHeight = child.getHeight();
+ child.layout((int) (centerX - width / 2.0f),
+ 0,
+ (int) (centerX + width / 2.0f),
+ (int) height);
+ updateChildOutline(child, width, height, oldWidth, oldHeight);
+ }
+ setMaxLayoutHeight(getHeight() - mEmptyMarginBottom);
+ updateScrollPositionIfNecessary();
+ updateChildren();
+ updateContentHeight();
+ }
+
+ private void setMaxLayoutHeight(int maxLayoutHeight) {
+ mMaxLayoutHeight = maxLayoutHeight;
+ updateAlgorithmHeight();
+ }
+
+ private void updateAlgorithmHeight() {
+ mStackScrollAlgorithm.setLayoutHeight(getLayoutHeight());
+ }
+
+ /**
+ * Updates the children views according to the stack scroll algorithm. Call this whenever
+ * modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
+ */
+ private void updateChildren() {
+ if (!isCurrentlyAnimating()) {
+ if (mCurrentStackScrollState == null) {
+ mCurrentStackScrollState = new StackScrollState(this);
+ }
+ mCurrentStackScrollState.setScrollY(mOwnScrollY);
+ mStackScrollAlgorithm.getStackScrollState(mCurrentStackScrollState);
+ mCurrentStackScrollState.apply();
+ mOwnScrollY = mCurrentStackScrollState.getScrollY();
+ } else {
+ // TODO: handle animation
+ }
+ }
+
+ private boolean isCurrentlyAnimating() {
+ return false;
+ }
+
+ private void updateChildOutline(View child,
+ float width,
+ float height,
+ int oldWidth,
+ int oldHeight) {
+ // The children currently have paddings inside themselfs because of the expansion
+ // visualization. In order for the shadows to work correctly we have to set the correct
+ // outline.
+ View container = child.findViewById(R.id.container);
+ if (container != null && (oldWidth != width || oldHeight != height)) {
+ Outline outline = getOutlineForSize(container.getLeft(),
+ container.getTop(),
+ container.getWidth(),
+ container.getHeight());
+ child.setOutline(outline);
+ }
+ }
+
+ private Outline getOutlineForSize(int leftInset, int topInset, int width, int height) {
+ Outline result = new Outline();
+ result.setRoundRect(leftInset, topInset, leftInset + width, topInset + height,
+ mBackgroundRoundedRectCornerRadius);
+ return result;
+ }
+
+ private void updateScrollPositionIfNecessary() {
+ int scrollRange = getScrollRange();
+ if (scrollRange < mOwnScrollY) {
+ mOwnScrollY = scrollRange;
+ }
+ }
+
+ public void setCurrentStackHeight(int currentStackHeight) {
+ this.mCurrentStackHeight = currentStackHeight;
+ updateAlgorithmHeight();
+ updateChildren();
+ }
+
+ /**
+ * Get the current height of the view. This is at most the size of the view given by a the
+ * layout but it can also be made smaller by setting {@link #mCurrentStackHeight}
+ *
+ * @return either the layout height or the externally defined height, whichever is smaller
+ */
+ private float getLayoutHeight() {
+ return Math.min(mMaxLayoutHeight, mCurrentStackHeight);
+ }
+
+ public void setLongPressListener(View.OnLongClickListener listener) {
+ mSwipeHelper.setLongPressListener(listener);
+ }
+
+ public void onChildDismissed(View v) {
+ if (DEBUG) Log.v(TAG, "onChildDismissed: " + v);
+ final View veto = v.findViewById(R.id.veto);
+ if (veto != null && veto.getVisibility() != View.GONE) {
+ veto.performClick();
+ }
+ allowScrolling(true);
+ }
+
+ public void onBeginDrag(View v) {
+ allowScrolling(false);
+ }
+
+ public void onDragCancelled(View v) {
+ allowScrolling(true);
+ }
+
+ public View getChildAtPosition(MotionEvent ev) {
+ return getChildAtPosition(ev.getX(), ev.getY());
+ }
+
+ public View getChildAtRawPosition(float touchX, float touchY) {
+ int[] location = new int[2];
+ getLocationOnScreen(location);
+ return getChildAtPosition(touchX - location[0],touchY - location[1]);
+ }
+
+ public View getChildAtPosition(float touchX, float touchY) {
+ // find the view under the pointer, accounting for GONE views
+ final int count = getChildCount();
+ for (int childIdx = 0; childIdx < count; childIdx++) {
+ View slidingChild = getChildAt(childIdx);
+ if (slidingChild.getVisibility() == GONE) {
+ continue;
+ }
+ float top = slidingChild.getTranslationY();
+ float bottom = top + slidingChild.getMeasuredHeight();
+ int left = slidingChild.getLeft();
+ int right = slidingChild.getRight();
+
+ if (touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
+ return slidingChild;
+ }
+ }
+ return null;
+ }
+
+ public boolean canChildBeExpanded(View v) {
+ return v instanceof ExpandableNotificationRow
+ && ((ExpandableNotificationRow) v).isExpandable();
+ }
+
+ public void setUserExpandedChild(View v, boolean userExpanded) {
+ if (v instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) v).setUserExpanded(userExpanded);
+ }
+ }
+
+ public void setUserLockedChild(View v, boolean userLocked) {
+ if (v instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) v).setUserLocked(userLocked);
+ }
+ }
+
+ public View getChildContentView(View v) {
+ return v;
+ }
+
+ public boolean canChildBeDismissed(View v) {
+ final View veto = v.findViewById(R.id.veto);
+ return (veto != null && veto.getVisibility() != View.GONE);
+ }
+
+ private void allowScrolling(boolean allow) {
+ mAllowScrolling = allow;
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ float densityScale = getResources().getDisplayMetrics().density;
+ mSwipeHelper.setDensityScale(densityScale);
+ float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
+ mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
+ initView(getContext());
+ }
+
+ public void dismissRowAnimated(View child, int vel) {
+ mSwipeHelper.dismissChild(child, vel);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ boolean scrollerWantsIt = false;
+ if (mAllowScrolling) {
+ scrollerWantsIt = onScrollTouch(ev);
+ }
+ boolean horizontalSwipeWantsIt = false;
+ if (!mIsBeingDragged) {
+ horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);
+ }
+ return horizontalSwipeWantsIt || scrollerWantsIt || super.onTouchEvent(ev);
+ }
+
+ private boolean onScrollTouch(MotionEvent ev) {
+ initVelocityTrackerIfNotExists();
+ mVelocityTracker.addMovement(ev);
+
+ final int action = ev.getAction();
+
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ if (getChildCount() == 0) {
+ return false;
+ }
+ boolean isBeingDragged = !mScroller.isFinished();
+ setIsBeingDragged(isBeingDragged);
+ if (isBeingDragged) {
+ final ViewParent parent = getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ }
+
+ /*
+ * If being flinged and user touches, stop the fling. isFinished
+ * will be false if being flinged.
+ */
+ if (!mScroller.isFinished()) {
+ mScroller.abortAnimation();
+ }
+
+ // Remember where the motion event started
+ mLastMotionY = (int) ev.getY();
+ mActivePointerId = ev.getPointerId(0);
+ break;
+ }
+ case MotionEvent.ACTION_MOVE:
+ final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
+ if (activePointerIndex == -1) {
+ Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent");
+ break;
+ }
+
+ final int y = (int) ev.getY(activePointerIndex);
+ int deltaY = mLastMotionY - y;
+ if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
+ final ViewParent parent = getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ setIsBeingDragged(true);
+ if (deltaY > 0) {
+ deltaY -= mTouchSlop;
+ } else {
+ deltaY += mTouchSlop;
+ }
+ }
+ if (mIsBeingDragged) {
+ // Scroll to follow the motion event
+ mLastMotionY = y;
+
+ final int oldX = mScrollX;
+ final int oldY = mOwnScrollY;
+ final int range = getScrollRange();
+ final int overscrollMode = getOverScrollMode();
+ final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
+ (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);
+
+ // Calling overScrollBy will call onOverScrolled, which
+ // calls onScrollChanged if applicable.
+ if (overScrollBy(0, deltaY, 0, mOwnScrollY,
+ 0, range, 0, mOverscrollDistance, true)) {
+ // Break our velocity if we hit a scroll barrier.
+ mVelocityTracker.clear();
+ }
+ // TODO: Overscroll
+// if (canOverscroll) {
+// final int pulledToY = oldY + deltaY;
+// if (pulledToY < 0) {
+// mEdgeGlowTop.onPull((float) deltaY / getHeight());
+// if (!mEdgeGlowBottom.isFinished()) {
+// mEdgeGlowBottom.onRelease();
+// }
+// } else if (pulledToY > range) {
+// mEdgeGlowBottom.onPull((float) deltaY / getHeight());
+// if (!mEdgeGlowTop.isFinished()) {
+// mEdgeGlowTop.onRelease();
+// }
+// }
+// if (mEdgeGlowTop != null
+// && (!mEdgeGlowTop.isFinished() || !mEdgeGlowBottom.isFinished())){
+// postInvalidateOnAnimation();
+// }
+// }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mIsBeingDragged) {
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
+
+ if (getChildCount() > 0) {
+ if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
+ fling(-initialVelocity);
+ } else {
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
+ getScrollRange())) {
+ postInvalidateOnAnimation();
+ }
+ }
+ }
+
+ mActivePointerId = INVALID_POINTER;
+ endDrag();
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ if (mIsBeingDragged && getChildCount() > 0) {
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
+ postInvalidateOnAnimation();
+ }
+ mActivePointerId = INVALID_POINTER;
+ endDrag();
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ final int index = ev.getActionIndex();
+ mLastMotionY = (int) ev.getY(index);
+ mActivePointerId = ev.getPointerId(index);
+ break;
+ }
+ case MotionEvent.ACTION_POINTER_UP:
+ onSecondaryPointerUp(ev);
+ mLastMotionY = (int) ev.getY(ev.findPointerIndex(mActivePointerId));
+ break;
+ }
+ return true;
+ }
+
+ private void onSecondaryPointerUp(MotionEvent ev) {
+ final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
+ MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ final int pointerId = ev.getPointerId(pointerIndex);
+ if (pointerId == mActivePointerId) {
+ // This was our active pointer going up. Choose a new
+ // active pointer and adjust accordingly.
+ // TODO: Make this decision more intelligent.
+ final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+ mLastMotionY = (int) ev.getY(newPointerIndex);
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ if (mVelocityTracker != null) {
+ mVelocityTracker.clear();
+ }
+ }
+ }
+
+ private void initVelocityTrackerIfNotExists() {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ }
+
+ private void recycleVelocityTracker() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ }
+
+ private void initOrResetVelocityTracker() {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ } else {
+ mVelocityTracker.clear();
+ }
+ }
+
+ @Override
+ public void computeScroll() {
+ if (mScroller.computeScrollOffset()) {
+ // This is called at drawing time by ViewGroup.
+ int oldX = mScrollX;
+ int oldY = mOwnScrollY;
+ int x = mScroller.getCurrX();
+ int y = mScroller.getCurrY();
+
+ if (oldX != x || oldY != y) {
+ final int range = getScrollRange();
+ final int overscrollMode = getOverScrollMode();
+ final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
+ (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);
+
+ overScrollBy(x - oldX, y - oldY, oldX, oldY, 0, range,
+ 0, mOverflingDistance, false);
+ onScrollChanged(mScrollX, mOwnScrollY, oldX, oldY);
+
+ if (canOverscroll) {
+ // TODO: Overscroll
+// if (y < 0 && oldY >= 0) {
+// mEdgeGlowTop.onAbsorb((int) mScroller.getCurrVelocity());
+// } else if (y > range && oldY <= range) {
+// mEdgeGlowBottom.onAbsorb((int) mScroller.getCurrVelocity());
+// }
+ }
+ updateChildren();
+ }
+
+ // Keep on drawing until the animation has finished.
+ postInvalidateOnAnimation();
+ }
+ }
+
+ public void customScrollBy(int y) {
+ mOwnScrollY += y;
+ updateChildren();
+ }
+
+ public void customScrollTo(int y) {
+ mOwnScrollY = y;
+ updateChildren();
+ }
+
+ @Override
+ protected void onOverScrolled(int scrollX, int scrollY,
+ boolean clampedX, boolean clampedY) {
+ // Treat animating scrolls differently; see #computeScroll() for why.
+ if (!mScroller.isFinished()) {
+ final int oldX = mScrollX;
+ final int oldY = mOwnScrollY;
+ mScrollX = scrollX;
+ mOwnScrollY = scrollY;
+ invalidateParentIfNeeded();
+ onScrollChanged(mScrollX, mOwnScrollY, oldX, oldY);
+ if (clampedY) {
+ mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange());
+ }
+ updateChildren();
+ } else {
+ customScrollTo(scrollY);
+ scrollTo(scrollX, mScrollY);
+ }
+ }
+
+ private int getScrollRange() {
+ int scrollRange = 0;
+ if (getChildCount() > 0) {
+ int contentHeight = getContentHeight();
+ scrollRange = Math.max(0,
+ contentHeight - mMaxLayoutHeight + mCollapsedSize);
+ }
+ return scrollRange;
+ }
+
+ private int getContentHeight() {
+ return mContentHeight;
+ }
+
+ private void updateContentHeight() {
+ int height = 0;
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ height += child.getHeight();
+ if (i < getChildCount()-1) {
+ height += mPaddingBetweenElements;
+ }
+ }
+ mContentHeight = height;
+ }
+
+ /**
+ * Fling the scroll view
+ *
+ * @param velocityY The initial velocity in the Y direction. Positive
+ * numbers mean that the finger/cursor is moving down the screen,
+ * which means we want to scroll towards the top.
+ */
+ private void fling(int velocityY) {
+ if (getChildCount() > 0) {
+ int height = (int) getLayoutHeight();
+ int bottom = getContentHeight();
+
+ mScroller.fling(mScrollX, mOwnScrollY, 0, velocityY, 0, 0, 0,
+ Math.max(0, bottom - height), 0, height/2);
+
+ postInvalidateOnAnimation();
+ }
+ }
+
+ private void endDrag() {
+ setIsBeingDragged(false);
+
+ recycleVelocityTracker();
+
+ // TODO: Overscroll
+// if (mEdgeGlowTop != null) {
+// mEdgeGlowTop.onRelease();
+// mEdgeGlowBottom.onRelease();
+// }
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ boolean scrollWantsIt = false;
+ if (mAllowScrolling) {
+ scrollWantsIt = onInterceptTouchEventScroll(ev);
+ }
+ boolean swipeWantsIt = false;
+ if (!mIsBeingDragged) {
+ swipeWantsIt = mSwipeHelper.onInterceptTouchEvent(ev);
+ }
+ return swipeWantsIt || scrollWantsIt ||
+ super.onInterceptTouchEvent(ev);
+ }
+
+ private boolean onInterceptTouchEventScroll(MotionEvent ev) {
+ /*
+ * This method JUST determines whether we want to intercept the motion.
+ * If we return true, onMotionEvent will be called and we do the actual
+ * scrolling there.
+ */
+
+ /*
+ * Shortcut the most recurring case: the user is in the dragging
+ * state and he is moving his finger. We want to intercept this
+ * motion.
+ */
+ final int action = ev.getAction();
+ if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
+ return true;
+ }
+
+ /*
+ * Don't try to intercept touch if we can't scroll anyway.
+ */
+ if (mOwnScrollY == 0 && getScrollRange() == 0) {
+ return false;
+ }
+
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_MOVE: {
+ /*
+ * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
+ * whether the user has moved far enough from his original down touch.
+ */
+
+ /*
+ * Locally do absolute value. mLastMotionY is set to the y value
+ * of the down event.
+ */
+ final int activePointerId = mActivePointerId;
+ if (activePointerId == INVALID_POINTER) {
+ // If we don't have a valid id, the touch down wasn't on content.
+ break;
+ }
+
+ final int pointerIndex = ev.findPointerIndex(activePointerId);
+ if (pointerIndex == -1) {
+ Log.e(TAG, "Invalid pointerId=" + activePointerId
+ + " in onInterceptTouchEvent");
+ break;
+ }
+
+ final int y = (int) ev.getY(pointerIndex);
+ final int yDiff = Math.abs(y - mLastMotionY);
+ if (yDiff > mTouchSlop) {
+ setIsBeingDragged(true);
+ mLastMotionY = y;
+ initVelocityTrackerIfNotExists();
+ mVelocityTracker.addMovement(ev);
+ final ViewParent parent = getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_DOWN: {
+ final int y = (int) ev.getY();
+ if (getChildAtPosition(ev.getX(), y) == null) {
+ setIsBeingDragged(false);
+ recycleVelocityTracker();
+ break;
+ }
+
+ /*
+ * Remember location of down touch.
+ * ACTION_DOWN always refers to pointer index 0.
+ */
+ mLastMotionY = y;
+ mActivePointerId = ev.getPointerId(0);
+
+ initOrResetVelocityTracker();
+ mVelocityTracker.addMovement(ev);
+ /*
+ * If being flinged and user touches the screen, initiate drag;
+ * otherwise don't. mScroller.isFinished should be false when
+ * being flinged.
+ */
+ boolean isBeingDragged = !mScroller.isFinished();
+ setIsBeingDragged(isBeingDragged);
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ /* Release the drag */
+ setIsBeingDragged(false);
+ mActivePointerId = INVALID_POINTER;
+ recycleVelocityTracker();
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
+ postInvalidateOnAnimation();
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ onSecondaryPointerUp(ev);
+ break;
+ }
+
+ /*
+ * The only time we want to intercept motion events is if we are in the
+ * drag mode.
+ */
+ return mIsBeingDragged;
+ }
+
+ private void setIsBeingDragged(boolean isDragged) {
+ mIsBeingDragged = isDragged;
+ if (isDragged) {
+ mSwipeHelper.removeLongPressCallback();
+ }
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ if (!hasWindowFocus) {
+ mSwipeHelper.removeLongPressCallback();
+ }
+ }
+
+ @Override
+ public boolean isScrolledToTop() {
+ return mOwnScrollY == 0;
+ }
+
+ @Override
+ public View getHostView() {
+ return this;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java
new file mode 100644
index 0000000..38b544f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 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.stack;
+
+import java.util.ArrayList;
+
+/**
+ * A Functor which interpolates the stack distance linearly based on base values.
+ * The base values are based on an interpolation between a linear function and a
+ * quadratic function
+ */
+public class PiecewiseLinearIndentationFunctor extends StackIndentationFunctor {
+
+ private final ArrayList<Float> mBaseValues;
+ private final float mLinearPart;
+
+ /**
+ * @param maxItemsInStack The maximum number of items which should be visible at the same time,
+ * i.e the function returns totalTransitionDistance for the element with
+ * index maxItemsInStack
+ * @param peekSize The visual appearance of this is how far the cards in the stack peek
+ * out below the top card and it is measured in real pixels.
+ * Note that the visual appearance does not necessarily always correspond to
+ * the actual visual distance below the top card but is a maximum,
+ * achieved when the next card just starts transitioning into the stack and
+ * the stack is full.
+ * If totalTransitionDistance is equal to this, we directly start at the peek,
+ * otherwise the first element transitions between 0 and
+ * totalTransitionDistance - peekSize.
+ * Visualization:
+ * --------------------------------------------------- ---
+ * | | |
+ * | FIRST ITEM | | <- totalTransitionDistance
+ * | | |
+ * |---------------------------------------------------| | ---
+ * |__________________SECOND ITEM______________________| | | <- peekSize
+ * |===================================================| _|_ _|_
+ *
+ * @param totalTransitionDistance The total transition distance an element has to go through
+ * @param linearPart The interpolation factor between the linear and the quadratic amount taken.
+ * This factor must be somewhere in [0 , 1]
+ */
+ PiecewiseLinearIndentationFunctor(int maxItemsInStack,
+ int peekSize,
+ int totalTransitionDistance,
+ float linearPart) {
+ super(maxItemsInStack, peekSize, totalTransitionDistance);
+ mBaseValues = new ArrayList<Float>(maxItemsInStack+1);
+ initBaseValues();
+ mLinearPart = linearPart;
+ }
+
+ private void initBaseValues() {
+ int sumOfSquares = getSumOfSquares(mMaxItemsInStack-1);
+ int totalWeight = 0;
+ mBaseValues.add(0.0f);
+ for (int i = 0; i < mMaxItemsInStack - 1; i++) {
+ totalWeight += (mMaxItemsInStack - i - 1) * (mMaxItemsInStack - i - 1);
+ mBaseValues.add((float) totalWeight / sumOfSquares);
+ }
+ }
+
+ /**
+ * Get the sum of squares up to and including n, i.e sum(i * i, 1, n)
+ *
+ * @param n the maximum square to include
+ * @return
+ */
+ private int getSumOfSquares(int n) {
+ return n * (n + 1) * (2 * n + 1) / 6;
+ }
+
+ @Override
+ public float getValue(float itemsBefore) {
+ if (mStackStartsAtPeek) {
+ // We directly start at the stack, so no initial interpolation.
+ itemsBefore++;
+ }
+ if (itemsBefore < 0) {
+ return 0;
+ } else if (itemsBefore >= mMaxItemsInStack) {
+ return mTotalTransitionDistance;
+ }
+ int below = (int) itemsBefore;
+ float partialIn = itemsBefore - below;
+
+ if (below == 0) {
+ return mDistanceToPeekStart * partialIn;
+ } else {
+ float result = mDistanceToPeekStart;
+ float progress = mBaseValues.get(below - 1) * (1 - partialIn)
+ + mBaseValues.get(below) * partialIn;
+ result += (progress * (1 - mLinearPart)
+ + (itemsBefore - 1) / (mMaxItemsInStack - 1) * mLinearPart) * mPeekSize;
+ return result;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java
new file mode 100644
index 0000000..f72947a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 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.stack;
+
+/**
+ * A functor which can be queried for offset given the number of items before it.
+ */
+public abstract class StackIndentationFunctor {
+
+ protected final int mTotalTransitionDistance;
+ protected final int mDistanceToPeekStart;
+ protected int mMaxItemsInStack;
+ protected int mPeekSize;
+ protected boolean mStackStartsAtPeek;
+
+ /**
+ * @param maxItemsInStack The maximum number of items which should be visible at the same time,
+ * i.e the function returns totalTransitionDistance for the element with
+ * index maxItemsInStack
+ * @param peekSize The visual appearance of this is how far the cards in the stack peek
+ * out below the top card and it is measured in real pixels.
+ * Note that the visual appearance does not necessarily always correspond to
+ * the actual visual distance below the top card but is a maximum,
+ * achieved when the next card just starts transitioning into the stack and
+ * the stack is full.
+ * If totalTransitionDistance is equal to this, we directly start at the peek,
+ * otherwise the first element transitions between 0 and
+ * totalTransitionDistance - peekSize.
+ * Visualization:
+ * --------------------------------------------------- ---
+ * | | |
+ * | FIRST ITEM | | <- totalTransitionDistance
+ * | | |
+ * |---------------------------------------------------| | ---
+ * |__________________SECOND ITEM______________________| | | <- peekSize
+ * |===================================================| _|_ _|_
+ *
+ * @param totalTransitionDistance The total transition distance an element has to go through
+ */
+ StackIndentationFunctor(int maxItemsInStack, int peekSize, int totalTransitionDistance) {
+ mTotalTransitionDistance = totalTransitionDistance;
+ mDistanceToPeekStart = mTotalTransitionDistance - peekSize;
+ mStackStartsAtPeek = mDistanceToPeekStart == 0;
+ mMaxItemsInStack = maxItemsInStack;
+ mPeekSize = peekSize;
+
+ }
+
+ public void setPeekSize(int mPeekSize) {
+ this.mPeekSize = mPeekSize;
+ }
+
+ /**
+ * Gets the offset of this Functor given a the quantity of items before it
+ *
+ * @param itemsBefore how many items are already in the stack before this element
+ * @return the offset
+ */
+ public abstract float getValue(float itemsBefore);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
new file mode 100644
index 0000000..9db4e77
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2014 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.stack;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.systemui.R;
+
+/**
+ * The Algorithm of the {@link com.android.systemui.statusbar.stack
+ * .NotificationStackScrollLayout} which can be queried for {@link com.android.systemui.statusbar
+ * .stack.StackScrollState}
+ */
+public class StackScrollAlgorithm {
+
+ private static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
+ private static final int MAX_ITEMS_IN_TOP_STACK = 3;
+
+ private int mPaddingBetweenElements;
+ private int mCollapsedSize;
+ private int mTopStackPeekSize;
+ private int mBottomStackPeekSize;
+ private int mZDistanceBetweenElements;
+ private int mZBasicHeight;
+
+ private StackIndentationFunctor mTopStackIndentationFunctor;
+ private StackIndentationFunctor mBottomStackIndentationFunctor;
+
+ private float mLayoutHeight;
+ private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
+
+ public StackScrollAlgorithm(Context context) {
+ initConstants(context);
+ }
+
+ private void initConstants(Context context) {
+
+ // currently the padding is in the elements themself
+ mPaddingBetweenElements = 0;
+ mCollapsedSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_row_min_height);
+ mTopStackPeekSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.top_stack_peek_amount);
+ mBottomStackPeekSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
+ mZDistanceBetweenElements = context.getResources()
+ .getDimensionPixelSize(R.dimen.z_distance_between_notifications);
+ mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
+
+ mTopStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
+ MAX_ITEMS_IN_TOP_STACK,
+ mTopStackPeekSize,
+ mCollapsedSize + mPaddingBetweenElements,
+ 0.5f);
+ mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
+ MAX_ITEMS_IN_BOTTOM_STACK,
+ mBottomStackPeekSize,
+ mBottomStackPeekSize,
+ 0.5f);
+ }
+
+
+ public void getStackScrollState(StackScrollState resultState) {
+ // The state of the local variables are saved in an algorithmState to easily subdivide it
+ // into multiple phases.
+ StackScrollAlgorithmState algorithmState = mTempAlgorithmState;
+
+ // First we reset the view states to their default values.
+ resultState.resetViewStates();
+
+ // The first element is always in there so it's initialized with 1.0f.
+ algorithmState.itemsInTopStack = 1.0f;
+ algorithmState.partialInTop = 0.0f;
+ algorithmState.lastTopStackIndex = 0;
+ algorithmState.scrollY = resultState.getScrollY();
+ algorithmState.itemsInBottomStack = 0.0f;
+
+ // Phase 1:
+ findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState);
+
+ // Phase 2:
+ updatePositionsForState(resultState, algorithmState);
+
+ // Phase 3:
+ updateZValuesForState(resultState, algorithmState);
+
+ // Write the algorithm state to the result.
+ resultState.setScrollY(algorithmState.scrollY);
+ }
+
+ /**
+ * Determine the positions for the views. This is the main part of the algorithm.
+ *
+ * @param resultState The result state to update if a change to the properties of a child occurs
+ * @param algorithmState The state in which the current pass of the algorithm is currently in
+ * and which will be updated
+ */
+ private void updatePositionsForState(StackScrollState resultState,
+ StackScrollAlgorithmState algorithmState) {
+ float stackHeight = getLayoutHeight();
+
+ // The position where the bottom stack starts.
+ float transitioningPositionStart = stackHeight - mCollapsedSize - mBottomStackPeekSize;
+
+ // The y coordinate of the current child.
+ float currentYPosition = 0.0f;
+
+ // How far in is the element currently transitioning into the bottom stack.
+ float yPositionInScrollView = 0.0f;
+
+ ViewGroup hostView = resultState.getHostView();
+ int childCount = hostView.getChildCount();
+ int numberOfElementsCompletelyIn = (int) algorithmState.itemsInTopStack;
+ for (int i = 0; i < childCount; i++) {
+ View child = hostView.getChildAt(i);
+ StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
+ childViewState.yTranslation = currentYPosition;
+ int childHeight = child.getHeight();
+ // The y position after this element
+ float nextYPosition = currentYPosition + childHeight + mPaddingBetweenElements;
+ float yPositionInScrollViewAfterElement = yPositionInScrollView
+ + childHeight
+ + mPaddingBetweenElements;
+ float scrollOffset = yPositionInScrollViewAfterElement - algorithmState.scrollY;
+ if (i < algorithmState.lastTopStackIndex) {
+ // Case 1:
+ // We are in the top Stack
+ nextYPosition = updateStateForTopStackChild(algorithmState,
+ numberOfElementsCompletelyIn,
+ i, childViewState);
+
+ } else if (i == algorithmState.lastTopStackIndex) {
+ // Case 2:
+ // First element of regular scrollview comes next, so the position is just the
+ // scrolling position
+ nextYPosition = scrollOffset;
+ } else if (nextYPosition >= transitioningPositionStart) {
+ if (currentYPosition >= transitioningPositionStart) {
+ // Case 3:
+ // According to the regular scroll view we are fully translated out of the
+ // bottom of the screen so we are fully in the bottom stack
+ nextYPosition = updateStateForChildFullyInBottomStack(algorithmState,
+ transitioningPositionStart, childViewState, childHeight);
+
+
+ } else {
+ // Case 4:
+ // According to the regular scroll view we are currently translating out of /
+ // into the bottom of the screen
+ nextYPosition = updateStateForChildTransitioningInBottom(
+ algorithmState, stackHeight, transitioningPositionStart,
+ currentYPosition, childViewState,
+ childHeight, nextYPosition);
+ }
+ }
+ currentYPosition = nextYPosition;
+ yPositionInScrollView = yPositionInScrollViewAfterElement;
+ }
+ }
+
+ private float updateStateForChildTransitioningInBottom(StackScrollAlgorithmState algorithmState,
+ float stackHeight, float transitioningPositionStart, float currentYPosition,
+ StackScrollState.ViewState childViewState, int childHeight, float nextYPosition) {
+ float newSize = transitioningPositionStart + mCollapsedSize - currentYPosition;
+ newSize = Math.min(childHeight, newSize);
+ // Transitioning element on top of bottom stack:
+ algorithmState.partialInBottom = 1.0f - (
+ (stackHeight - mBottomStackPeekSize - nextYPosition) / mCollapsedSize);
+ // Our element can be expanded, so we might even have to scroll further than
+ // mCollapsedSize
+ algorithmState.partialInBottom = Math.min(1.0f, algorithmState.partialInBottom);
+ float offset = mBottomStackIndentationFunctor.getValue(
+ algorithmState.partialInBottom);
+ nextYPosition = transitioningPositionStart + offset;
+ algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
+ // TODO: only temporarily collapse
+ if (childHeight != (int) newSize) {
+ childViewState.height = (int) newSize;
+ }
+ return nextYPosition;
+ }
+
+ private float updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
+ float transitioningPositionStart, StackScrollState.ViewState childViewState,
+ int childHeight) {
+
+ float nextYPosition;
+ algorithmState.itemsInBottomStack += 1.0f;
+ if (algorithmState.itemsInBottomStack < MAX_ITEMS_IN_BOTTOM_STACK) {
+ // We are visually entering the bottom stack
+ nextYPosition = transitioningPositionStart
+ + mBottomStackIndentationFunctor.getValue(
+ algorithmState.itemsInBottomStack);
+ } else {
+ // we are fully inside the stack
+ if (algorithmState.itemsInBottomStack > MAX_ITEMS_IN_BOTTOM_STACK + 2) {
+ childViewState.alpha = 0.0f;
+ } else if (algorithmState.itemsInBottomStack
+ > MAX_ITEMS_IN_BOTTOM_STACK + 1) {
+ childViewState.alpha = 1.0f - algorithmState.partialInBottom;
+ }
+ nextYPosition = transitioningPositionStart + mBottomStackPeekSize;
+ }
+ // TODO: only temporarily collapse
+ if (childHeight != mCollapsedSize) {
+ childViewState.height = mCollapsedSize;
+ }
+ return nextYPosition;
+ }
+
+ private float updateStateForTopStackChild(StackScrollAlgorithmState algorithmState,
+ int numberOfElementsCompletelyIn, int i, StackScrollState.ViewState childViewState) {
+
+ float nextYPosition = 0;
+
+ // First we calculate the index relative to the current stack window of size at most
+ // {@link #MAX_ITEMS_IN_TOP_STACK}
+ int paddedIndex = i
+ - Math.max(numberOfElementsCompletelyIn - MAX_ITEMS_IN_TOP_STACK, 0);
+ if (paddedIndex >= 0) {
+ // We are currently visually entering the top stack
+ nextYPosition = mCollapsedSize + mPaddingBetweenElements -
+ mTopStackIndentationFunctor.getValue(
+ algorithmState.itemsInTopStack - i - 1);
+ if (paddedIndex == 0 && i != 0) {
+ childViewState.alpha = 1.0f - algorithmState.partialInTop;
+ }
+ } else {
+ // We are hidden behind the top card and faded out, so we can hide ourselfs
+ if (i != 0) {
+ childViewState.alpha = 0.0f;
+ }
+ }
+ return nextYPosition;
+ }
+
+ /**
+ * Find the number of items in the top stack and update the result state if needed.
+ *
+ * @param resultState The result state to update if a height change of an child occurs
+ * @param algorithmState The state in which the current pass of the algorithm is currently in
+ * and which will be updated
+ */
+ private void findNumberOfItemsInTopStackAndUpdateState(StackScrollState resultState,
+ StackScrollAlgorithmState algorithmState) {
+
+ // The y Position if the element would be in a regular scrollView
+ float yPositionInScrollView = 0.0f;
+ ViewGroup hostView = resultState.getHostView();
+ int childCount = hostView.getChildCount();
+
+ // find the number of elements in the top stack.
+ for (int i = 0; i < childCount; i++) {
+ View child = hostView.getChildAt(i);
+ StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
+ int childHeight = child.getHeight();
+ float yPositionInScrollViewAfterElement = yPositionInScrollView
+ + childHeight
+ + mPaddingBetweenElements;
+ if (yPositionInScrollView < algorithmState.scrollY) {
+ if (yPositionInScrollViewAfterElement <= algorithmState.scrollY) {
+ // According to the regular scroll view we are fully off screen
+ algorithmState.itemsInTopStack += 1.0f;
+ if (childHeight != mCollapsedSize) {
+ childViewState.height = mCollapsedSize;
+ }
+ } else {
+ // According to the regular scroll view we are partially off screen
+ // If it is expanded we have to collapse it to a new size
+ float newSize = yPositionInScrollViewAfterElement
+ - mPaddingBetweenElements
+ - algorithmState.scrollY;
+
+ // How much did we scroll into this child
+ algorithmState.partialInTop = (mCollapsedSize - newSize) / (mCollapsedSize
+ + mPaddingBetweenElements);
+
+ // Our element can be expanded, so this can get negative
+ algorithmState.partialInTop = Math.max(0.0f, algorithmState.partialInTop);
+ algorithmState.itemsInTopStack += algorithmState.partialInTop;
+ // TODO: handle overlapping sizes with end stack
+ newSize = Math.max(mCollapsedSize, newSize);
+ // TODO: only temporarily collapse
+ if (newSize != childHeight) {
+ childViewState.height = (int) newSize;
+
+ // We decrease scrollY by the same amount we made this child smaller.
+ // The new scroll position is therefore the start of the element
+ algorithmState.scrollY = (int) yPositionInScrollView;
+ resultState.setScrollY(algorithmState.scrollY);
+ }
+ if (childHeight > mCollapsedSize) {
+ // If we are just resizing this child, this element is not treated to be
+ // transitioning into the stack and therefore it is the last element in
+ // the stack.
+ algorithmState.lastTopStackIndex = i;
+ break;
+ }
+ }
+ } else {
+ algorithmState.lastTopStackIndex = i;
+
+ // We are already past the stack so we can end the loop
+ break;
+ }
+ yPositionInScrollView = yPositionInScrollViewAfterElement;
+ }
+ }
+
+ /**
+ * Calculate the Z positions for all children based on the number of items in both stacks and
+ * save it in the resultState
+ *
+ * @param resultState The result state to update the zTranslation values
+ * @param algorithmState The state in which the current pass of the algorithm is currently in
+ */
+ private void updateZValuesForState(StackScrollState resultState,
+ StackScrollAlgorithmState algorithmState) {
+ ViewGroup hostView = resultState.getHostView();
+ int childCount = hostView.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = hostView.getChildAt(i);
+ StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
+ if (i < algorithmState.itemsInTopStack) {
+ float stackIndex = algorithmState.itemsInTopStack - i;
+ stackIndex = Math.min(stackIndex, MAX_ITEMS_IN_TOP_STACK + 2);
+ childViewState.zTranslation = mZBasicHeight
+ + stackIndex * mZDistanceBetweenElements;
+ } else if (i > (childCount - 1 - algorithmState.itemsInBottomStack)) {
+ float numItemsAbove = i - (childCount - 1 - algorithmState.itemsInBottomStack);
+ float translationZ = mZBasicHeight
+ - numItemsAbove * mZDistanceBetweenElements;
+ childViewState.zTranslation = translationZ;
+ } else {
+ childViewState.zTranslation = mZBasicHeight;
+ }
+ }
+ }
+
+ public float getLayoutHeight() {
+ return mLayoutHeight;
+ }
+
+ public void setLayoutHeight(float layoutHeight) {
+ this.mLayoutHeight = layoutHeight;
+ }
+
+ class StackScrollAlgorithmState {
+
+ /**
+ * The scroll position of the algorithm
+ */
+ public int scrollY;
+
+ /**
+ * The quantity of items which are in the top stack.
+ */
+ public float itemsInTopStack;
+
+ /**
+ * how far in is the element currently transitioning into the top stack
+ */
+ public float partialInTop;
+
+ /**
+ * The last item index which is in the top stack.
+ * NOTE: In the top stack the item after the transitioning element is also in the stack!
+ * This is needed to ensure a smooth transition between the y position in the regular
+ * scrollview and the one in the stack.
+ */
+ public int lastTopStackIndex;
+
+ /**
+ * The quantity of items which are in the bottom stack.
+ */
+ public float itemsInBottomStack;
+
+ /**
+ * how far in is the element currently transitioning into the bottom stack
+ */
+ public float partialInBottom;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
new file mode 100644
index 0000000..f72a52f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2014 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.stack;
+
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A state of a {@link com.android.systemui.statusbar.stack.NotificationStackScrollLayout} which
+ * can be applied to a viewGroup.
+ */
+public class StackScrollState {
+
+ private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
+
+ private final ViewGroup mHostView;
+ private Map<View, ViewState> mStateMap;
+ private int mScrollY;
+
+ public int getScrollY() {
+ return mScrollY;
+ }
+
+ public void setScrollY(int scrollY) {
+ this.mScrollY = scrollY;
+ }
+
+ public StackScrollState(ViewGroup hostView) {
+ mHostView = hostView;
+ mStateMap = new HashMap<View, ViewState>(mHostView.getChildCount());
+ }
+
+ public ViewGroup getHostView() {
+ return mHostView;
+ }
+
+ public void resetViewStates() {
+ int numChildren = mHostView.getChildCount();
+ for (int i = 0; i < numChildren; i++) {
+ View child = mHostView.getChildAt(i);
+ ViewState viewState = mStateMap.get(child);
+ if (viewState == null) {
+ viewState = new ViewState();
+ mStateMap.put(child, viewState);
+ }
+ // initialize with the default values of the view
+ viewState.height = child.getHeight();
+ viewState.alpha = 1.0f;
+ }
+ }
+
+
+ public ViewState getViewStateForView(View requestedView) {
+ return mStateMap.get(requestedView);
+ }
+
+ /**
+ * Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
+ * The properties are only applied if they effectively changed.
+ */
+ public void apply() {
+ int numChildren = mHostView.getChildCount();
+ for (int i = 0; i < numChildren; i++) {
+ View child = mHostView.getChildAt(i);
+ ViewState state = mStateMap.get(child);
+ if (state != null) {
+ float alpha = child.getAlpha();
+ float yTranslation = child.getTranslationY();
+ float zTranslation = child.getTranslationZ();
+ int height = child.getHeight();
+ float newAlpha = state.alpha;
+ float newYTranslation = state.yTranslation;
+ float newZTranslation = state.zTranslation;
+ int newHeight = state.height;
+ boolean becomesInvisible = newAlpha == 0.0f;
+ if (alpha != newAlpha) {
+ // apply layer type
+ boolean becomesFullyVisible = newAlpha == 1.0f;
+ boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible;
+ int layerType = child.getLayerType();
+ int newLayerType = newLayerTypeIsHardware
+ ? View.LAYER_TYPE_HARDWARE
+ : View.LAYER_TYPE_NONE;
+ if (layerType != newLayerType) {
+ child.setLayerType(newLayerType, null);
+ }
+
+ // apply alpha
+ if (!becomesInvisible) {
+ child.setAlpha(newAlpha);
+ }
+ }
+
+ // apply visibility
+ int oldVisibility = child.getVisibility();
+ int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
+ if (newVisibility != oldVisibility) {
+ child.setVisibility(newVisibility);
+ }
+
+ // apply yTranslation
+ if (yTranslation != newYTranslation) {
+ child.setTranslationY(newYTranslation);
+ }
+
+ // apply zTranslation
+ if (zTranslation != newZTranslation) {
+ child.setTranslationZ(newZTranslation);
+ }
+
+ // apply height
+ if (height != newHeight) {
+ applyNewHeight(child, newHeight);
+ }
+ } else {
+ Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
+ "to the hostView");
+ }
+ }
+ }
+
+ private void applyNewHeight(View child, int newHeight) {
+ ViewGroup.LayoutParams lp = child.getLayoutParams();
+ lp.height = newHeight;
+ child.setLayoutParams(lp);
+ }
+
+
+ public class ViewState {
+ float alpha;
+ float yTranslation;
+ float zTranslation;
+ int height;
+ }
+}
diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
index fb002d2..5c8a8ef 100644
--- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
+++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
@@ -365,12 +365,6 @@ public class WallpaperCropActivity extends Activity {
Point inSize = mCropView.getSourceDimensions();
- // Due to rounding errors in the cropview renderer the edges can be slightly offset
- // therefore we ensure that the boundaries are sanely defined
- cropRect.left = Math.max(0, cropRect.left);
- cropRect.right = Math.min(inSize.x, cropRect.right);
- cropRect.top = Math.max(0, cropRect.top);
- cropRect.bottom = Math.min(inSize.y, cropRect.bottom);
int cropRotation = mCropView.getImageRotation();
float cropScale = mCropView.getWidth() / (float) cropRect.width();
@@ -381,6 +375,13 @@ public class WallpaperCropActivity extends Activity {
rotatedInSize[0] = Math.abs(rotatedInSize[0]);
rotatedInSize[1] = Math.abs(rotatedInSize[1]);
+ // Due to rounding errors in the cropview renderer the edges can be slightly offset
+ // therefore we ensure that the boundaries are sanely defined
+ cropRect.left = Math.max(0, cropRect.left);
+ cropRect.right = Math.min(rotatedInSize[0], cropRect.right);
+ cropRect.top = Math.max(0, cropRect.top);
+ cropRect.bottom = Math.min(rotatedInSize[1], cropRect.bottom);
+
// ADJUST CROP WIDTH
// Extend the crop all the way to the right, for parallax
// (or all the way to the left, in RTL)
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index b7c1704..2f56e62 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1751,7 +1751,8 @@ class AppWidgetServiceImpl {
for (int i = 0; i < N; i++) {
AppWidgetId id = mAppWidgetIds.get(i);
if (backupTarget.equals(id.host.packageName)
- || backupTarget.equals(id.provider.info.provider.getPackageName())) {
+ || (id.provider != null && backupTarget.equals(
+ id.provider.info.provider.getPackageName()))) {
serializeAppWidgetId(out, id);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3db3a26..36e53a3 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1189,6 +1189,7 @@ final class ActivityStack {
// At this point, nothing else needs to be shown
if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
behindFullscreen = true;
+ showHomeBehindStack = false;
} else if (isActivityOverHome(r)) {
if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
showHomeBehindStack = true;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3bc7f4f..ccd6f60 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -65,8 +65,8 @@ import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.AtomicFile;
-import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -76,7 +76,6 @@ import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
import com.android.internal.R;
-
import com.android.internal.notification.NotificationScorer;
import com.android.server.EventLogTags;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -169,7 +168,8 @@ public class NotificationManagerService extends SystemService {
// used as a mutex for access to all active notifications & listeners
final ArrayList<NotificationRecord> mNotificationList =
new ArrayList<NotificationRecord>();
-
+ final ArrayMap<String, NotificationRecord> mNotificationsByKey =
+ new ArrayMap<String, NotificationRecord>();
final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>();
@@ -661,6 +661,7 @@ public class NotificationManagerService extends SystemService {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
+ boolean added = false;
synchronized (mNotificationList) {
mServicesBinding.remove(servicesBindingTag);
try {
@@ -669,11 +670,20 @@ public class NotificationManagerService extends SystemService {
= new NotificationListenerInfo(
mListener, name, userid, this);
service.linkToDeath(info, 0);
- mListeners.add(info);
+ added = mListeners.add(info);
} catch (RemoteException e) {
// already dead
}
}
+ if (added) {
+ final String[] keys =
+ getActiveNotificationKeysFromListener(mListener);
+ try {
+ mListener.onListenerConnected(keys);
+ } catch (RemoteException e) {
+ // we tried
+ }
+ }
}
@Override
@@ -763,7 +773,7 @@ public class NotificationManagerService extends SystemService {
}
}
- private NotificationListenerInfo checkListenerToken(INotificationListener listener) {
+ private NotificationListenerInfo checkListenerTokenLocked(INotificationListener listener) {
checkNullListener(listener);
final IBinder token = listener.asBinder();
final int N = mListeners.size();
@@ -799,6 +809,7 @@ public class NotificationManagerService extends SystemService {
pw.println(prefix + " icon=0x" + Integer.toHexString(notification.icon)
+ " / " + idDebugString(baseContext, sbn.getPackageName(), notification.icon));
pw.println(prefix + " pri=" + notification.priority + " score=" + sbn.getScore());
+ pw.println(prefix + " key=" + sbn.getKey());
pw.println(prefix + " contentIntent=" + notification.contentIntent);
pw.println(prefix + " deleteIntent=" + notification.deleteIntent);
pw.println(prefix + " tickerText=" + notification.tickerText);
@@ -855,10 +866,11 @@ public class NotificationManagerService extends SystemService {
@Override
public final String toString() {
return String.format(
- "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d: %s)",
+ "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
System.identityHashCode(this),
this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
- this.sbn.getTag(), this.sbn.getScore(), this.sbn.getNotification());
+ this.sbn.getTag(), this.sbn.getScore(), this.sbn.getKey(),
+ this.sbn.getNotification());
}
}
@@ -927,7 +939,9 @@ public class NotificationManagerService extends SystemService {
@Override
public void onClearAll(int callingUid, int callingPid, int userId) {
- cancelAll(callingUid, callingPid, userId, REASON_DELEGATE_CANCEL_ALL, null);
+ synchronized (mNotificationList) {
+ cancelAllLocked(callingUid, callingPid, userId, REASON_DELEGATE_CANCEL_ALL, null);
+ }
}
@Override
@@ -1552,19 +1566,40 @@ public class NotificationManagerService extends SystemService {
* @param token The binder for the listener, to check that the caller is allowed
*/
@Override
- public void cancelAllNotificationsFromListener(INotificationListener token) {
- NotificationListenerInfo info = checkListenerToken(token);
+ public void cancelNotificationsFromListener(INotificationListener token, String[] keys) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
long identity = Binder.clearCallingIdentity();
try {
- cancelAll(callingUid, callingPid, info.userid,
- REASON_LISTENER_CANCEL_ALL, info);
+ synchronized (mNotificationList) {
+ final NotificationListenerInfo info = checkListenerTokenLocked(token);
+ if (keys != null) {
+ final int N = keys.length;
+ for (int i = 0; i < N; i++) {
+ NotificationRecord r = mNotificationsByKey.get(keys[i]);
+ if (r != null) {
+ cancelNotificationFromListenerLocked(info, callingUid, callingPid,
+ r.sbn.getPackageName(), r.sbn.getTag(), r.sbn.getId());
+ }
+ }
+ } else {
+ cancelAllLocked(callingUid, callingPid, info.userid,
+ REASON_LISTENER_CANCEL_ALL, info);
+ }
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
}
+ private void cancelNotificationFromListenerLocked(NotificationListenerInfo info,
+ int callingUid, int callingPid, String pkg, String tag, int id) {
+ cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
+ Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
+ true,
+ info.userid, REASON_LISTENER_CANCEL, info);
+ }
+
/**
* Allow an INotificationListener to simulate clearing (dismissing) a single notification.
*
@@ -1575,15 +1610,15 @@ public class NotificationManagerService extends SystemService {
@Override
public void cancelNotificationFromListener(INotificationListener token, String pkg,
String tag, int id) {
- NotificationListenerInfo info = checkListenerToken(token);
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
long identity = Binder.clearCallingIdentity();
try {
- cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
- Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
- true,
- info.userid, REASON_LISTENER_CANCEL, info);
+ synchronized (mNotificationList) {
+ final NotificationListenerInfo info = checkListenerTokenLocked(token);
+ cancelNotificationFromListenerLocked(info, callingUid, callingPid,
+ pkg, tag, id);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1598,21 +1633,35 @@ public class NotificationManagerService extends SystemService {
*/
@Override
public StatusBarNotification[] getActiveNotificationsFromListener(
- INotificationListener token) {
- NotificationListenerInfo info = checkListenerToken(token);
-
- StatusBarNotification[] result = new StatusBarNotification[0];
- ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>();
+ INotificationListener token, String[] keys) {
synchronized (mNotificationList) {
- final int N = mNotificationList.size();
- for (int i=0; i<N; i++) {
- StatusBarNotification sbn = mNotificationList.get(i).sbn;
- if (info.enabledAndUserMatches(sbn)) {
- list.add(sbn);
+ final NotificationListenerInfo info = checkListenerTokenLocked(token);
+ final ArrayList<StatusBarNotification> list
+ = new ArrayList<StatusBarNotification>();
+ if (keys == null) {
+ final int N = mNotificationList.size();
+ for (int i=0; i<N; i++) {
+ StatusBarNotification sbn = mNotificationList.get(i).sbn;
+ if (info.enabledAndUserMatches(sbn)) {
+ list.add(sbn);
+ }
+ }
+ } else {
+ final int N = keys.length;
+ for (int i=0; i<N; i++) {
+ NotificationRecord r = mNotificationsByKey.get(keys[i]);
+ if (r != null && info.enabledAndUserMatches(r.sbn)) {
+ list.add(r.sbn);
+ }
}
}
+ return list.toArray(new StatusBarNotification[list.size()]);
}
- return list.toArray(result);
+ }
+
+ @Override
+ public String[] getActiveNotificationKeysFromListener(INotificationListener token) {
+ return NotificationManagerService.this.getActiveNotificationKeysFromListener(token);
}
@Override
@@ -1629,6 +1678,21 @@ public class NotificationManagerService extends SystemService {
}
};
+ private String[] getActiveNotificationKeysFromListener(INotificationListener token) {
+ synchronized (mNotificationList) {
+ final NotificationListenerInfo info = checkListenerTokenLocked(token);
+ final ArrayList<String> keys = new ArrayList<String>();
+ final int N = mNotificationList.size();
+ for (int i=0; i<N; i++) {
+ final StatusBarNotification sbn = mNotificationList.get(i).sbn;
+ if (info.enabledAndUserMatches(sbn)) {
+ keys.add(sbn.getKey());
+ }
+ }
+ return keys.toArray(new String[keys.size()]);
+ }
+ }
+
void dumpImpl(PrintWriter pw) {
pw.println("Current Notification Manager state:");
@@ -1850,6 +1914,10 @@ public class NotificationManagerService extends SystemService {
old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
}
}
+ if (old != null) {
+ mNotificationsByKey.remove(old.sbn.getKey());
+ }
+ mNotificationsByKey.put(n.getKey(), r);
// Ensure if this is a foreground service that the proper additional
// flags are set.
@@ -2327,6 +2395,7 @@ public class NotificationManagerService extends SystemService {
}
mNotificationList.remove(index);
+ mNotificationsByKey.remove(r.sbn.getKey());
cancelNotificationLocked(r, sendDelete);
updateLightsLocked();
@@ -2399,6 +2468,7 @@ public class NotificationManagerService extends SystemService {
return true;
}
mNotificationList.remove(i);
+ mNotificationsByKey.remove(r.sbn.getKey());
cancelNotificationLocked(r, false);
}
if (canceledSomething) {
@@ -2446,29 +2516,26 @@ public class NotificationManagerService extends SystemService {
}
}
- void cancelAll(int callingUid, int callingPid, int userId, int reason,
+ void cancelAllLocked(int callingUid, int callingPid, int userId, int reason,
NotificationListenerInfo listener) {
EventLogTags.writeNotificationCancelAll(callingUid, callingPid,
null, userId, 0, 0, reason,
listener == null ? null : listener.component.toShortString());
- synchronized (mNotificationList) {
- final int N = mNotificationList.size();
- for (int i=N-1; i>=0; i--) {
- NotificationRecord r = mNotificationList.get(i);
-
- if (!notificationMatchesUserIdOrRelated(r, userId)) {
- continue;
- }
-
- if ((r.getFlags() & (Notification.FLAG_ONGOING_EVENT
- | Notification.FLAG_NO_CLEAR)) == 0) {
- mNotificationList.remove(i);
- cancelNotificationLocked(r, true);
- }
+ final int N = mNotificationList.size();
+ for (int i=N-1; i>=0; i--) {
+ NotificationRecord r = mNotificationList.get(i);
+ if (!notificationMatchesUserIdOrRelated(r, userId)) {
+ continue;
}
- updateLightsLocked();
+ if ((r.getFlags() & (Notification.FLAG_ONGOING_EVENT
+ | Notification.FLAG_NO_CLEAR)) == 0) {
+ mNotificationList.remove(i);
+ mNotificationsByKey.remove(r.sbn.getKey());
+ cancelNotificationLocked(r, true);
+ }
}
+ updateLightsLocked();
}
// lock on mNotificationList
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a01c586..a07ad5a 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -69,6 +69,7 @@ import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
@@ -340,7 +341,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Lock for state used when installing and doing other long running
// operations. Methods that must be called with this lock held have
- // the prefix "LI".
+ // the suffix "LI".
final Object mInstallLock = new Object();
// These are the directories in the 3rd party applications installed dir
@@ -916,6 +917,14 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.i(TAG, "Observer no longer exists.");
}
}
+ if (args.observer2 != null) {
+ try {
+ Bundle extras = extrasForInstallResult(res);
+ args.observer2.packageInstalled(res.name, extras, res.returnCode);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Observer no longer exists.");
+ }
+ }
} else {
Slog.e(TAG, "Bogus post-install token " + msg.arg1);
}
@@ -1044,6 +1053,21 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ Bundle extrasForInstallResult(PackageInstalledInfo res) {
+ Bundle extras = null;
+ switch (res.returnCode) {
+ case PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION: {
+ extras = new Bundle();
+ extras.putString(PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION,
+ res.origPermission);
+ extras.putString(PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE,
+ res.origPackage);
+ break;
+ }
+ }
+ return extras;
+ }
+
void scheduleWriteSettingsLocked() {
if (!mHandler.hasMessages(WRITE_SETTINGS)) {
mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
@@ -6772,18 +6796,24 @@ public class PackageManagerService extends IPackageManager.Stub {
private final boolean mIsPrivileged;
}
+ /*
+ * The old-style observer methods all just trampoline to the newer signature with
+ * expanded install observer API. The older API continues to work but does not
+ * supply the additional details of the Observer2 API.
+ */
+
/* Called when a downloaded package installation has been confirmed by the user */
public void installPackage(
final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
- installPackage(packageURI, observer, flags, null);
+ installPackageEtc(packageURI, observer, null, flags, null);
}
/* Called when a downloaded package installation has been confirmed by the user */
public void installPackage(
final Uri packageURI, final IPackageInstallObserver observer, final int flags,
final String installerPackageName) {
- installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
- null, null);
+ installPackageWithVerificationEtc(packageURI, observer, null, flags,
+ installerPackageName, null, null, null);
}
@Override
@@ -6792,20 +6822,67 @@ public class PackageManagerService extends IPackageManager.Stub {
ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
VerificationParams.NO_UID, manifestDigest);
- installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+ installPackageWithVerificationAndEncryptionEtc(packageURI, observer, null, flags,
installerPackageName, verificationParams, encryptionParams);
}
public void installPackageWithVerificationAndEncryption(Uri packageURI,
IPackageInstallObserver observer, int flags, String installerPackageName,
VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ installPackageWithVerificationAndEncryptionEtc(packageURI, observer, null, flags,
+ installerPackageName, verificationParams, encryptionParams);
+ }
+
+ /*
+ * And here are the "live" versions that take both observer arguments
+ */
+ public void installPackageEtc(
+ final Uri packageURI, final IPackageInstallObserver observer,
+ IPackageInstallObserver2 observer2, final int flags) {
+ installPackageEtc(packageURI, observer, observer2, flags, null);
+ }
+
+ public void installPackageEtc(
+ final Uri packageURI, final IPackageInstallObserver observer,
+ final IPackageInstallObserver2 observer2, final int flags,
+ final String installerPackageName) {
+ installPackageWithVerificationEtc(packageURI, observer, observer2, flags,
+ installerPackageName, null, null, null);
+ }
+
+ @Override
+ public void installPackageWithVerificationEtc(Uri packageURI, IPackageInstallObserver observer,
+ IPackageInstallObserver2 observer2,
+ int flags, String installerPackageName, Uri verificationURI,
+ ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
+ VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
+ VerificationParams.NO_UID, manifestDigest);
+ installPackageWithVerificationAndEncryptionEtc(packageURI, observer, observer2, flags,
+ installerPackageName, verificationParams, encryptionParams);
+ }
+
+ /*
+ * All of the installPackage...*() methods redirect to this one for the master implementation
+ */
+ public void installPackageWithVerificationAndEncryptionEtc(Uri packageURI,
+ IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+ int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ if (observer == null && observer2 == null) {
+ throw new IllegalArgumentException("No install observer supplied");
+ }
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
null);
final int uid = Binder.getCallingUid();
if (isUserRestricted(UserHandle.getUserId(uid), UserManager.DISALLOW_INSTALL_APPS)) {
try {
- observer.packageInstalled("", PackageManager.INSTALL_FAILED_USER_RESTRICTED);
+ if (observer != null) {
+ observer.packageInstalled("", PackageManager.INSTALL_FAILED_USER_RESTRICTED);
+ }
+ if (observer2 != null) {
+ observer2.packageInstalled("", null, PackageManager.INSTALL_FAILED_USER_RESTRICTED);
+ }
} catch (RemoteException re) {
}
return;
@@ -6832,8 +6909,8 @@ public class PackageManagerService extends IPackageManager.Stub {
verificationParams.setInstallerUid(uid);
final Message msg = mHandler.obtainMessage(INIT_COPY);
- msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
- verificationParams, encryptionParams, user);
+ msg.obj = new InstallParams(packageURI, observer, observer2, filteredFlags,
+ installerPackageName, verificationParams, encryptionParams, user);
mHandler.sendMessage(msg);
}
@@ -7522,6 +7599,7 @@ public class PackageManagerService extends IPackageManager.Stub {
class InstallParams extends HandlerParams {
final IPackageInstallObserver observer;
+ final IPackageInstallObserver2 observer2;
int flags;
private final Uri mPackageURI;
@@ -7533,13 +7611,14 @@ public class PackageManagerService extends IPackageManager.Stub {
final ContainerEncryptionParams encryptionParams;
InstallParams(Uri packageURI,
- IPackageInstallObserver observer, int flags,
- String installerPackageName, VerificationParams verificationParams,
+ IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+ int flags, String installerPackageName, VerificationParams verificationParams,
ContainerEncryptionParams encryptionParams, UserHandle user) {
super(user);
this.mPackageURI = packageURI;
this.flags = flags;
this.observer = observer;
+ this.observer2 = observer2;
this.installerPackageName = installerPackageName;
this.verificationParams = verificationParams;
this.encryptionParams = encryptionParams;
@@ -8109,6 +8188,7 @@ public class PackageManagerService extends IPackageManager.Stub {
static abstract class InstallArgs {
final IPackageInstallObserver observer;
+ final IPackageInstallObserver2 observer2;
// Always refers to PackageManager flags only
final int flags;
final Uri packageURI;
@@ -8116,12 +8196,14 @@ public class PackageManagerService extends IPackageManager.Stub {
final ManifestDigest manifestDigest;
final UserHandle user;
- InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
- String installerPackageName, ManifestDigest manifestDigest,
+ InstallArgs(Uri packageURI,
+ IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+ int flags, String installerPackageName, ManifestDigest manifestDigest,
UserHandle user) {
this.packageURI = packageURI;
this.flags = flags;
this.observer = observer;
+ this.observer2 = observer2;
this.installerPackageName = installerPackageName;
this.manifestDigest = manifestDigest;
this.user = user;
@@ -8178,13 +8260,13 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean created = false;
FileInstallArgs(InstallParams params) {
- super(params.getPackageUri(), params.observer, params.flags,
+ super(params.getPackageUri(), params.observer, params.observer2, params.flags,
params.installerPackageName, params.getManifestDigest(),
params.getUser());
}
FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
- super(null, null, 0, null, null, null);
+ super(null, null, null, 0, null, null, null);
File codeFile = new File(fullCodePath);
installDir = codeFile.getParentFile();
codeFileName = fullCodePath;
@@ -8193,7 +8275,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
- super(packageURI, null, 0, null, null, null);
+ super(packageURI, null, null, 0, null, null, null);
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
String apkName = getNextCodePath(null, pkgName, ".apk");
codeFileName = new File(installDir, apkName + ".apk").getPath();
@@ -8514,14 +8596,14 @@ public class PackageManagerService extends IPackageManager.Stub {
String libraryPath;
AsecInstallArgs(InstallParams params) {
- super(params.getPackageUri(), params.observer, params.flags,
+ super(params.getPackageUri(), params.observer, params.observer2, params.flags,
params.installerPackageName, params.getManifestDigest(),
params.getUser());
}
AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
boolean isExternal, boolean isForwardLocked) {
- super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
+ super(null, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
null, null, null);
// Extract cid from fullCodePath
@@ -8533,7 +8615,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
AsecInstallArgs(String cid, boolean isForwardLocked) {
- super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
+ super(null, null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
null, null, null);
this.cid = cid;
@@ -8541,7 +8623,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
- super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
+ super(packageURI, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
null, null, null);
this.cid = cid;
@@ -8875,6 +8957,10 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.Package pkg;
int returnCode;
PackageRemovedInfo removedInfo;
+
+ // In some error cases we want to convey more info back to the observer
+ String origPackage;
+ String origPermission;
}
/*
@@ -9299,6 +9385,27 @@ public class PackageManagerService extends IPackageManager.Stub {
String oldCodePath = null;
boolean systemApp = false;
synchronized (mPackages) {
+ // Check whether the newly-scanned package wants to define an already-defined perm
+ int N = pkg.permissions.size();
+ for (int i = 0; i < N; i++) {
+ PackageParser.Permission perm = pkg.permissions.get(i);
+ BasePermission bp = mSettings.mPermissions.get(perm.info.name);
+ if (bp != null) {
+ // If the defining package is signed with our cert, it's okay. This
+ // also includes the "updating the same package" case, of course.
+ if (compareSignatures(bp.packageSetting.signatures.mSignatures,
+ pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
+ Slog.w(TAG, "Package " + pkg.packageName
+ + " attempting to redeclare permission " + perm.info.name
+ + " already owned by " + bp.sourcePackage);
+ res.returnCode = PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
+ res.origPermission = perm.info.name;
+ res.origPackage = bp.sourcePackage;
+ return;
+ }
+ }
+ }
+
// Check if installing already existing package
if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
String oldName = mSettings.mRenamedPackages.get(pkgName);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0558b5a..dcf5880 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -920,6 +920,10 @@ public class WindowManagerService extends IWindowManager.Stub
final IWindow client = win.mClient;
final WindowToken token = win.mToken;
final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent == null) {
+ // It doesn't matter this display is going away.
+ return 0;
+ }
final WindowList windows = win.getWindowList();
final int N = windows.size();
@@ -1097,6 +1101,9 @@ public class WindowManagerService extends IWindowManager.Stub
private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
final WindowToken token = win.mToken;
final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent == null) {
+ return;
+ }
final WindowState attached = win.mAttachedWindow;
WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
@@ -2254,6 +2261,11 @@ public class WindowManagerService extends IWindowManager.Stub
return WindowManagerGlobal.ADD_APP_EXITING;
}
+ if (win.getDisplayContent() == null) {
+ Slog.w(TAG, "Adding window to Display that has been removed.");
+ return WindowManagerGlobal.ADD_INVALID_DISPLAY;
+ }
+
mPolicy.adjustWindowParamsLw(win.mAttrs);
win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
@@ -2743,7 +2755,7 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
- final DisplayInfo displayInfo = window.getDisplayContent().getDisplayInfo();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
final RectF dispRect = new RectF(0, 0,
displayInfo.logicalWidth, displayInfo.logicalHeight);
matrix.mapRect(dispRect);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6b3c368..3c9d53e 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -176,9 +176,15 @@ class WindowStateAnimator {
mAnimator = service.mAnimator;
mPolicy = service.mPolicy;
mContext = service.mContext;
- final DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo();
- mAnimDw = displayInfo.appWidth;
- mAnimDh = displayInfo.appHeight;
+ final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent != null) {
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ mAnimDw = displayInfo.appWidth;
+ mAnimDh = displayInfo.appHeight;
+ } else {
+ Slog.w(TAG, "WindowStateAnimator ctor: Display has been removed");
+ // This is checked on return and dealt with.
+ }
mWin = win;
mAttachedWinAnimator = win.mAttachedWindow == null
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index c26a516..a58b00bce 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -365,7 +365,9 @@ static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativ
int result = impl->set(type, &ts);
if (result < 0)
{
- ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
+ ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
+ static_cast<long long>(seconds),
+ static_cast<long long>(nanoseconds), strerror(errno));
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f186b2c..983ca2d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -170,7 +170,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int mActivePasswordNonLetter = 0;
int mFailedPasswordAttempts = 0;
- int mUserHandle;;
+ int mUserHandle;
int mPasswordOwner = -1;
long mLastMaximumTimeToLock = -1;
@@ -722,6 +722,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int callingUid = Binder.getCallingUid();
final int userHandle = UserHandle.getUserId(callingUid);
final DevicePolicyData policy = getUserData(userHandle);
+
+ List<ActiveAdmin> candidates = new ArrayList<ActiveAdmin>();
+
+ // Build a list of admins for this uid matching the given ComponentName
if (who != null) {
ActiveAdmin admin = policy.mAdminMap.get(who);
if (admin == null) {
@@ -731,22 +735,43 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
throw new SecurityException("Admin " + who + " is not owned by uid "
+ Binder.getCallingUid());
}
- if (!admin.info.usesPolicy(reqPolicy)) {
- throw new SecurityException("Admin " + admin.info.getComponent()
- + " did not specify uses-policy for: "
- + admin.info.getTagForPolicy(reqPolicy));
- }
- return admin;
+ candidates.add(admin);
} else {
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
+ for (ActiveAdmin admin : policy.mAdminList) {
+ if (admin.getUid() == callingUid) {
+ candidates.add(admin);
+ }
+ }
+ }
+
+ // Try to find an admin which can use reqPolicy
+ for (ActiveAdmin admin : candidates) {
+ boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
+ boolean ownsProfile = (getProfileOwner(userHandle) != null
+ && getProfileOwner(userHandle).equals(admin.info.getPackageName()));
+
+ if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
+ if (ownsDevice) {
+ return admin;
+ }
+ } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
+ if (ownsDevice || ownsProfile) {
+ return admin;
+ }
+ } else {
+ if (admin.info.usesPolicy(reqPolicy)) {
return admin;
}
}
+ }
+
+ if (who != null) {
+ throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
+ + " did not specify uses-policy for: "
+ + candidates.get(0).info.getTagForPolicy(reqPolicy));
+ } else {
throw new SecurityException("No active admin owned by uid "
- + Binder.getCallingUid() + " for policy #" + reqPolicy);
+ + Binder.getCallingUid() + " for policy:" + reqPolicy);
}
}
@@ -2966,64 +2991,41 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- private boolean isProfileOwner(String packageName, int userId) {
- String profileOwnerPackage = getProfileOwner(userId);
- // TODO: make public and connect with isProfileOwnerApp in DPM
- return profileOwnerPackage != null && profileOwnerPackage.equals(packageName);
- }
-
- public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter,
+ public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
ComponentName activity) {
- int callingUserId = UserHandle.getCallingUserId();
- Slog.d(LOG_TAG,"called by user " + callingUserId);
synchronized (this) {
- ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
- if (aa == null) {
- throw new SecurityException("No active admin " + admin);
- } else {
- if (isProfileOwner(admin.getPackageName(), callingUserId)
- || isDeviceOwner(admin.getPackageName())) {
- IPackageManager pm = AppGlobals.getPackageManager();
- long id = Binder.clearCallingIdentity();
- try {
- pm.addPersistentPreferredActivity(filter, activity, callingUserId);
- } catch (RemoteException re) {
- // Shouldn't happen
- } finally {
- restoreCallingIdentity(id);
- }
- } else {
- throw new SecurityException("Admin " + admin +
- "is not device owner or profile owner" );
- }
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ IPackageManager pm = AppGlobals.getPackageManager();
+ long id = Binder.clearCallingIdentity();
+ try {
+ pm.addPersistentPreferredActivity(filter, activity, UserHandle.getCallingUserId());
+ } catch (RemoteException re) {
+ // Shouldn't happen
+ } finally {
+ restoreCallingIdentity(id);
}
}
}
- public void clearPackagePersistentPreferredActivities(ComponentName admin,
- String packageName) {
- int callingUserId = UserHandle.getCallingUserId();
- Slog.d(LOG_TAG,"called by user " + callingUserId);
+ public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
synchronized (this) {
- ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
- if (aa == null) {
- throw new SecurityException("No active admin " + admin);
- } else {
- if (isProfileOwner(admin.getPackageName(), callingUserId)
- || isDeviceOwner(admin.getPackageName())) {
- IPackageManager pm = AppGlobals.getPackageManager();
- long id = Binder.clearCallingIdentity();
- try{
- pm.clearPackagePersistentPreferredActivities(packageName, callingUserId);
- } catch (RemoteException re) {
- // Shouldn't happen
- } finally {
- restoreCallingIdentity(id);
- }
- } else {
- throw new SecurityException("Admin " + admin +
- "is not device owner or profile owner" );
- }
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ IPackageManager pm = AppGlobals.getPackageManager();
+ long id = Binder.clearCallingIdentity();
+ try {
+ pm.clearPackagePersistentPreferredActivities(packageName, UserHandle.getCallingUserId());
+ } catch (RemoteException re) {
+ // Shouldn't happen
+ } finally {
+ restoreCallingIdentity(id);
}
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c925669..7b55f4b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -116,6 +116,8 @@ public final class SystemServer {
"com.android.server.usb.UsbService$Lifecycle";
private static final String WIFI_SERVICE_CLASS =
"com.android.server.wifi.WifiService";
+ private static final String WIFI_HOTSPOT_SERVICE_CLASS =
+ "com.android.server.wifi.hotspot.WifiHotspotService";
private static final String WIFI_P2P_SERVICE_CLASS =
"com.android.server.wifi.p2p.WifiP2pService";
private static final String HDMI_CEC_SERVICE_CLASS =
@@ -614,6 +616,12 @@ public final class SystemServer {
}
try {
+ mSystemServiceManager.startService(WIFI_HOTSPOT_SERVICE_CLASS);
+ } catch (Throwable e) {
+ reportWtf("starting Wi-Fi HotspotService", e);
+ }
+
+ try {
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting Wi-Fi Service", e);
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 323e0ac..1c75658 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -101,8 +101,93 @@ public class DisconnectCause {
/** Unknown error or not specified */
public static final int ERROR_UNSPECIFIED = 36;
+ /** Smallest valid value for call disconnect codes. */
+ public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
+ /** Largest valid value for call disconnect codes. */
+ public static final int MAXIMUM_VALID_VALUE = ERROR_UNSPECIFIED;
+
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
// Do nothing.
}
+
+ /** Returns descriptive string for the specified disconnect cause. */
+ public static String toString(int cause) {
+ switch (cause) {
+ case NOT_DISCONNECTED:
+ return "NOT_DISCONNECTED";
+ case INCOMING_MISSED:
+ return "INCOMING_MISSED";
+ case NORMAL:
+ return "NORMAL";
+ case LOCAL:
+ return "LOCAL";
+ case BUSY:
+ return "BUSY";
+ case CONGESTION:
+ return "CONGESTION";
+ case INVALID_NUMBER:
+ return "INVALID_NUMBER";
+ case NUMBER_UNREACHABLE:
+ return "NUMBER_UNREACHABLE";
+ case SERVER_UNREACHABLE:
+ return "SERVER_UNREACHABLE";
+ case INVALID_CREDENTIALS:
+ return "INVALID_CREDENTIALS";
+ case OUT_OF_NETWORK:
+ return "OUT_OF_NETWORK";
+ case SERVER_ERROR:
+ return "SERVER_ERROR";
+ case TIMED_OUT:
+ return "TIMED_OUT";
+ case LOST_SIGNAL:
+ return "LOST_SIGNAL";
+ case LIMIT_EXCEEDED:
+ return "LIMIT_EXCEEDED";
+ case INCOMING_REJECTED:
+ return "INCOMING_REJECTED";
+ case POWER_OFF:
+ return "POWER_OFF";
+ case OUT_OF_SERVICE:
+ return "OUT_OF_SERVICE";
+ case ICC_ERROR:
+ return "ICC_ERROR";
+ case CALL_BARRED:
+ return "CALL_BARRED";
+ case FDN_BLOCKED:
+ return "FDN_BLOCKED";
+ case CS_RESTRICTED:
+ return "CS_RESTRICTED";
+ case CS_RESTRICTED_NORMAL:
+ return "CS_RESTRICTED_NORMAL";
+ case CS_RESTRICTED_EMERGENCY:
+ return "CS_RESTRICTED_EMERGENCY";
+ case UNOBTAINABLE_NUMBER:
+ return "UNOBTAINABLE_NUMBER";
+ case CDMA_LOCKED_UNTIL_POWER_CYCLE:
+ return "CDMA_LOCKED_UNTIL_POWER_CYCLE";
+ case CDMA_DROP:
+ return "CDMA_DROP";
+ case CDMA_INTERCEPT:
+ return "CDMA_INTERCEPT";
+ case CDMA_REORDER:
+ return "CDMA_REORDER";
+ case CDMA_SO_REJECT:
+ return "CDMA_SO_REJECT";
+ case CDMA_RETRY_ORDER:
+ return "CDMA_RETRY_ORDER";
+ case CDMA_ACCESS_FAILURE:
+ return "CDMA_ACCESS_FAILURE";
+ case CDMA_PREEMPTED:
+ return "CDMA_PREEMPTED";
+ case CDMA_NOT_EMERGENCY:
+ return "CDMA_NOT_EMERGENCY";
+ case CDMA_ACCESS_BLOCKED:
+ return "CDMA_ACCESS_BLOCKED";
+ case ERROR_UNSPECIFIED:
+ return "ERROR_UNSPECIFIED";
+ default:
+ return "INVALID";
+ }
+ }
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 118cba4..daef37a 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -16,6 +16,7 @@
package android.test.mock;
+import android.app.PackageInstallObserver;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -664,4 +665,34 @@ public class MockPackageManager extends PackageManager {
public VerifierDeviceIdentity getVerifierDeviceIdentity() {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public void installPackage(Uri packageURI, PackageInstallObserver observer,
+ int flags, String installerPackageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void installPackageWithVerification(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ Uri verificationURI, ManifestDigest manifestDigest,
+ ContainerEncryptionParams encryptionParams) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void installPackageWithVerificationAndEncryption(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tests/DynamicDrawableTest/Android.mk b/tests/DynamicDrawableTest/Android.mk
new file mode 100644
index 0000000..5c51301
--- /dev/null
+++ b/tests/DynamicDrawableTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := DynamicDrawableTest
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/DynamicDrawableTest/AndroidManifest.xml b/tests/DynamicDrawableTest/AndroidManifest.xml
new file mode 100644
index 0000000..4ca3e3c
--- /dev/null
+++ b/tests/DynamicDrawableTest/AndroidManifest.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.dynamic" >
+ <uses-sdk android:minSdkVersion="11" />
+
+ <application
+ android:hardwareAccelerated="true"
+ android:label="vector" >
+ <activity
+ android:name="VectorDrawableTest"
+ android:label="Vector Icon" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="VectorDrawable01"
+ android:label="VectorTest1" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="VectorDrawablePerformance"
+ android:label="Vector Performance" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+
+ <activity
+ android:name="VectorDrawableDupPerf"
+ android:label="Vector Performance of clones" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ <activity
+ android:name="VectorDrawableStaticPerf"
+ android:label="Performance of vector images" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+
+ <activity
+ android:name="VectorCheckbox"
+ android:label="On a Checkbox" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ <activity
+ android:name="VectorPathChecking"
+ android:label="Path Checking graphics" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/tests/DynamicDrawableTest/lint.xml b/tests/DynamicDrawableTest/lint.xml
new file mode 100644
index 0000000..ee0eead
--- /dev/null
+++ b/tests/DynamicDrawableTest/lint.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+</lint> \ No newline at end of file
diff --git a/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png b/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..60fbdf5
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/tests/DynamicDrawableTest/res/drawable/icon.png b/tests/DynamicDrawableTest/res/drawable/icon.png
new file mode 100644
index 0000000..cb40a19
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/icon.png
Binary files differ
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml
new file mode 100644
index 0000000..4f4b386
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml
@@ -0,0 +1,73 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:trigger="state_checked" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="480"
+ android:viewportWidth="480" />
+
+ <group>
+ <path
+ android:name="check"
+ android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z"
+ android:fill="#ffff00ff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="5" />
+ </group>
+ <group>
+ <path
+ android:name="box1"
+ android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
+ android:fill="#ffffffff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="5" />
+ </group>
+ <group>
+ <path
+ android:name="box2"
+ android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
+ android:fill="#ff000000"
+ android:rotation="46.757"
+ android:pivotX="162"
+ android:pivotY="173.5"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="5" />
+ </group>
+ <group>
+ <path
+ android:name="box3"
+ android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z"
+ android:stroke="#FF000000"
+ android:strokeWidth="4" />
+ </group>
+ <group>
+ <path
+ android:name="box4"
+ android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z"
+ android:stroke="#FF000000"
+ android:strokeWidth="30" />
+ </group>
+
+ <animation
+ android:durations="300,100,0,300"
+ android:sequence="check,box1,box2,box3,box4" />
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml
new file mode 100644
index 0000000..49906d17
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml
@@ -0,0 +1,46 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="320"
+ android:viewportHeight="320"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M 100,225 L 100,115 L 130,115 L 70,15 L 10,115 L 40,115 L 40,225 z"
+ android:fill="#ffffffff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+ </group>
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M 130,225 L 130,115 L 130,115 L 70,15 L 10,115 L 10,115 L 10,225 z"
+ android:fill="#ff440000"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="180"
+ android:pivotX="70"
+ android:pivotY="120"
+ android:trimPathStart=".1"
+ android:trimPathEnd=".9"/>
+ </group>
+ <animation android:sequence="arrow,house"/>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml
new file mode 100644
index 0000000..137049d
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml
@@ -0,0 +1,137 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="7.30625"
+ android:viewportHeight="12.25"/>
+
+ <group>
+
+ <path
+ android:name="clip1"
+ android:pathData="
+ M 0, 0
+ l 7.3, 0
+ l 0, 0
+ l -7.3, 0
+ z"
+ android:clipToPath="true"
+ android:rotation="-30"
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ />
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ff88ff"
+ />
+ <path
+ android:name="clip2"
+ android:pathData="
+ M 0, 0
+ l 7.3, 0
+ l 0, 12.25
+ l -7.3, 0
+ z"
+ android:clipToPath="true"
+ android:rotation="-30"
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ff88ff"
+ />
+ </group>
+ <group>
+ <path
+ android:name="clip1"
+ android:pathData="
+ M 0, 0
+ l 7.3, 0
+ l 0, 12.25
+ l -7.3, 0
+ z"
+ android:clipToPath="true"
+ android:rotation="-30"
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ />
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ff88ff"
+ />
+ <path
+ android:name="clip2"
+ android:pathData="
+ M 0, 12.25
+ l 7.3, 0
+ l 0, 12.25
+ l -7.3, 0
+ z"
+ android:clipToPath="true"
+ android:rotation="-30"
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ff88ff"
+ />
+ </group>
+
+
+ <animation
+ android:sequence="one,one"
+ android:durations="4000"/>
+ <animation
+ android:sequence="two,two"
+ android:durations="4000"/>
+ <animation
+ android:sequence="clip1,clip1"
+ android:durations="4000"/>
+ <animation
+ android:sequence="clip2,clip2"
+ android:durations="4000"/>
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml
new file mode 100644
index 0000000..cffb73f
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml
@@ -0,0 +1,126 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="7.30625"
+ android:viewportHeight="12.25"/>
+
+ <group>
+ <path
+ android:name="clip1"
+ android:pathData="
+ M 3.65, 6.125
+ m -.001, 0
+ a .001,.001 0 1,0 .002,0
+ a .001,.001 0 1,0 -.002,0z"
+ android:clipToPath="true"
+ android:fill="#112233"
+ />
+
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ff88ff"
+ />
+ <path
+ android:name="clip2"
+ android:pathData="
+ M 3.65, 6.125
+ m -6, 0
+ a 6,6 0 1,0 12,0
+ a 6,6 0 1,0 -12,0z"
+ android:clipToPath="true"
+ android:fill="#112233"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ff88ff"
+ />
+ </group>
+ <group>
+ <path
+ android:name="clip1"
+ android:pathData="
+ M 3.65, 6.125
+ m -6, 0
+ a 6,6 0 1,0 12,0
+ a 6,6 0 1,0 -12,0z"
+ android:clipToPath="true"
+ android:fill="#332233"
+ />
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ff88ff"
+ />
+ <path
+ android:name="clip2"
+ android:pathData="
+ M 3.65, 6.125
+ m -.001, 0
+ a .001,.001 0 1,0 .002,0
+ a .001,.001 0 1,0 -.002,0z"
+ android:clipToPath="true"
+ android:fill="#662233"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ff88ff"
+ />
+ </group>
+
+
+
+ <animation
+ android:sequence="one,one"
+ android:durations="4000"/>
+ <animation
+ android:sequence="two,two"
+ android:durations="4000"/>
+ <animation
+ android:sequence="clip1,clip1"
+ android:durations="4000"/>
+ <animation
+ android:sequence="clip2,clip2"
+ android:durations="4000"/>
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml
new file mode 100644
index 0000000..bcf3ae6
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml
@@ -0,0 +1,147 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="7.30625"
+ android:viewportHeight="12.25"/>
+
+ <group>
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ffff00"
+ />
+
+
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ffff00"
+ android:fillOpacity="0"
+ />
+ </group>
+ <group>
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ffff00"
+ android:fillOpacity="0"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ffff00"
+ />
+ </group>
+ <group>
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ffff00"
+ />
+ <path
+ android:name="three"
+ android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
+ q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125
+ q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125
+ l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625
+ q 1.109375,0.0 1.6875,-0.4375 0.59375,-0.4375 0.59375,-1.28125
+ q 0.0,-0.765625 -0.546875,-1.203125 -0.546875,-0.4375 -1.5,-0.4375
+ l -1.03125,0.0 0.0,-0.96875 1.078125,0.0q 0.859375,0.0 1.328125,-0.34375
+ q 0.46875,-0.359375 0.46875,-1.015625 0.0,-0.671875 -0.484375,-1.03125
+ q -0.46875,-0.359375 -1.359375,-0.359375 -0.5,0.0 -1.0625,0.109375
+ q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125
+ q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375
+ q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375
+ q -0.40625,0.5 -1.171875,0.6875Z"
+ android:fill="#ffff00"
+ android:fillOpacity="0"
+ />
+ </group>
+ <group>
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ffff00"
+ android:fillOpacity="0"
+ />
+ <path
+ android:name="three"
+ android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
+ q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125
+ q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125
+ l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625
+ q 1.109375,0.0 1.6875,-0.4375 0.59375,-0.4375 0.59375,-1.28125
+ q 0.0,-0.765625 -0.546875,-1.203125 -0.546875,-0.4375 -1.5,-0.4375
+ l -1.03125,0.0 0.0,-0.96875 1.078125,0.0q 0.859375,0.0 1.328125,-0.34375
+ q 0.46875,-0.359375 0.46875,-1.015625 0.0,-0.671875 -0.484375,-1.03125
+ q -0.46875,-0.359375 -1.359375,-0.359375 -0.5,0.0 -1.0625,0.109375
+ q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125
+ q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375
+ q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375
+ q -0.40625,0.5 -1.171875,0.6875Z"
+ android:fill="#ffff00"
+ />
+ </group>
+
+
+ <animation
+ android:sequence="one,one,three,three"
+ android:durations="2000,0,2000"/>
+ <animation
+ android:sequence="two,two,two,two"
+ android:durations="2000,0,2000"/>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml
new file mode 100644
index 0000000..73ff5e2
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml
@@ -0,0 +1,76 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="700"
+ android:viewportHeight="700"/>
+
+ <group>
+ </group>
+ <path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
+ android:name="path2451"
+ android:stroke="#FF000000"
+ android:strokeWidth="30.65500000000000"/>
+ <path android:pathData="M 365.015 311.066"
+ android:name="path2453"
+ android:stroke="#FF000000"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928"
+ android:name="path2455"
+ android:stroke="#FF000000"
+ android:fill="#FF0000FF"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 170.515 451.566L 305.61 313.46"
+ android:name="path2457"
+ android:stroke="#000000"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 557.968 449.974L 426.515 315.375"
+ android:name="path2459"
+ android:stroke="#000000"
+ android:strokeWidth="30.655000000000001"/>
+ <group>
+ <path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
+ android:name="path2451"
+ android:stroke="#FF000000"
+ android:strokeWidth="30.65500000000000"/>
+ <path android:pathData="M 365.015 311.066"
+ android:name="path2453"
+ android:stroke="#FF000000"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928"
+ android:name="path2455"
+ android:stroke="#FF000000"
+ android:fill="#FFFFFFFF"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 170.515 451.566L 305.61 313.46"
+ android:name="path2457"
+ android:stroke="#000000"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 557.968 449.974L 426.515 315.375"
+ android:name="path2459"
+ android:stroke="#000000"
+ android:strokeWidth="30.655000000000001"/>
+ </group>
+
+ <animation android:sequence="path2451,path2451"
+ android:durations="1000"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml
new file mode 100644
index 0000000..99d37ef
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml
@@ -0,0 +1,45 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="140"
+ android:viewportHeight="110"/>
+ <group>
+ <path
+ android:name="menu"
+ android:pathData="M 20,20 l 100,0 0,10 -100,0 z
+ M 20,50 l 100,0 0,10 -100,0 z
+ M 20,80 l 0,-10 100,0 0,10 z"
+ android:fill="#ffffffff"/>
+ </group>
+ <group>
+ <path
+ android:name="back"
+ android:pathData="M 20,55 l 35.3,-35.3 7.07,7.07 -35.3,35.3 z
+ M 27,50 l 97,0 0,10 -97,0 z
+ M 20,55 l 7.07,-7.07 35.3,35.3 -7.07,7.07 z"
+ android:fill="#ffffffff"
+ android:rotation="180"
+ android:pivotX="70"
+ android:pivotY="55"
+ />
+ </group>
+ <animation android:sequence="menu,back"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml
new file mode 100644
index 0000000..f8a03d7
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml
@@ -0,0 +1,48 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="600"
+ android:viewportHeight="600"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M535.441,412.339A280.868,280.868 0 1,1 536.186,161.733L284.493,286.29Z"
+ android:fill="#ffffcc00"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+ </group>
+
+ <group>
+ <path
+ android:name="pie2"
+ android:pathData="M564.441,287A280.868,280.868 0 1,1 564.441,285L284.493,286.29Z"
+ android:fill="#FFccaa00"
+ android:stroke="#FF000000"
+ android:strokeWidth="10"
+ android:pivotX="90"
+ android:pivotY="100"/>
+ </group>
+
+ <animation android:sequence="pie1,pie2"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml
new file mode 100644
index 0000000..09934de
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml
@@ -0,0 +1,41 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="200"
+ android:viewportHeight="200"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M 20,20 l 60,0 0,140 -60,0 z M 120,20 l 60,0 0,140 -60,0 z"
+ android:fill="#ffffffff"/>
+ </group>
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M 100,20 l 0,0 0,140 -80,0 z M 100,20 l 0,0 80,140 -80,0 z"
+ android:fill="#ffffffff"
+ android:rotation="90"
+ android:pivotX="100"
+ android:pivotY="100"/>
+ </group>
+ <animation android:sequence="arrow,house"/>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml
new file mode 100644
index 0000000..f17f67a
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="200"
+ android:viewportWidth="200" />
+
+ <group>
+ <path
+ android:name="bar3"
+ android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
+ android:fill="#FF555555" />
+ <path
+ android:name="bar1"
+ android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
+ android:fill="#FF555555" />
+ <path
+ android:name="bar0"
+ android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
+ android:fill="#FF555555" />
+ </group>
+ <group>
+ <path
+ android:name="bar3"
+ android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar1"
+ android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
+ android:fill="#FF555555" />
+ <path
+ android:name="bar0"
+ android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
+ android:fill="#FF555555" />
+ </group>
+
+ <group>
+ <path
+ android:name="bar3"
+ android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar1"
+ android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar0"
+ android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
+ android:fill="#FF555555" />
+ </group>
+
+ <group>
+ <path
+ android:name="bar3"
+ android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar1"
+ android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar0"
+ android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
+ android:fill="#FFFFFFFF" />
+ </group>
+
+ <animation
+ android:sequence="bar0,bar0,bar0,bar0"
+ android:durations="500,500,500"/>
+ <animation
+ android:sequence="bar1,bar1,bar1,bar1"
+ android:durations="500,500,500"/>
+ <animation
+ android:sequence="bar2,bar2,bar2,bar2"
+ android:durations="500,500,500"/>
+ <animation
+ android:sequence="bar3,bar3,bar3,bar3"
+ android:durations="500,500,500"/>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml
new file mode 100644
index 0000000..a1a03be
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml
@@ -0,0 +1,62 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="80"
+ android:viewportWidth="40" />
+
+ <group>
+ <path
+ android:name="battery"
+ android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
+ android:fill="#3388ff"
+ android:stroke="#ff8833"
+ android:strokeWidth="1"
+ android:rotation="0"/>
+ <path
+ android:name="spark"
+ android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z"
+ android:fill="#FFFF0000" />
+
+ </group>
+ <group>
+ <path
+ android:name="battery"
+ android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
+ android:fill="#ff8833"
+ android:stroke="#3388ff"
+ android:strokeWidth="1"
+ android:rotation="0" />
+ <path
+ android:name="spark"
+ android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z"
+ android:fill="#FFFF0000" />
+ </group>
+
+ <animation
+ android:durations="2000"
+ android:sequence="spark,spark" />
+ <animation
+ android:durations="2000"
+ android:sequence="battery,battery" />
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml
new file mode 100644
index 0000000..89748d5
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml
@@ -0,0 +1,90 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="600"
+ android:viewportHeight="600"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="70"
+ android:trimPathStart="0"
+ android:trimPathEnd=".75"
+ android:trimPathOffset="0"/>
+
+ <path
+ android:name="v"
+ android:pathData="M300,70 l 0,-70 70,70 -70,70z"
+ android:fill="#FF00FF00"
+ android:pivotX="300"
+ android:pivotY="300"
+ android:rotation="0"
+ />
+ </group>
+
+ <group>
+ <path
+ android:name="v"
+ android:pathData="M300,70 l 0,-70 70,70 -70,70z"
+ android:pivotX="300"
+ android:pivotY="300"
+ android:rotation="360"/>
+ <path
+ android:name="pie2"
+ android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="70"
+ android:rotation="360"
+ android:pivotX="300"
+ android:pivotY="300"
+ android:trimPathStart="0"
+ android:trimPathEnd=".5"
+ android:trimPathOffset="0"
+ android:strokeLineCap="round"
+ />
+ </group>
+
+ <animation android:sequence="pie1,pie2"
+ android:durations="2000"
+ android:startOffset="500"
+ android:repeatCount="-1"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+ <animation android:sequence="v,v"
+ android:durations="2000"
+ android:startOffset="500"
+ android:repeatCount="-1"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+ <animation android:sequence="pie1,pie2"
+ android:durations="2800"
+ android:startOffset="500"
+ android:limitTo="trimPathEnd"
+ android:repeatCount="-1"
+ android:repeatStyle="reverse"
+ android:animate="easeInOut"
+ />
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml
new file mode 100644
index 0000000..43dda52
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml
@@ -0,0 +1,82 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="600"
+ android:viewportHeight="400"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+ android:fill="#ffffffff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+
+ <path
+ android:name="half"
+ android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+ android:fill="#FFFF0000"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="5"
+ android:rotation="0"
+ android:pivotX="300"
+ android:pivotY="200"/>
+ </group>
+
+ <group>
+ <path
+ android:name="pie2"
+ android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+ android:fill="#ffff0000"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="300"
+ android:pivotY="200"/>
+
+ <path
+ android:name="half"
+ android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+ android:fill="#FFFFFF00"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="5"
+ android:rotation="-360"
+ android:pivotX="300"
+ android:pivotY="200"/>
+ </group>
+ <animation android:sequence="pie1,pie2"
+ android:durations="1000"
+ android:startOffset="500"
+ android:repeatCount="2"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+ <animation android:sequence="half,half"
+ android:durations="1000"
+ android:startOffset="500"
+ android:repeatCount="5"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml
new file mode 100644
index 0000000..0f1f149
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml
@@ -0,0 +1,54 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="800"
+ android:viewportHeight="500"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M200,450 l 50,-25
+ a25,25 -30 0,1 100,-50 l 50,-25
+ a25,50 -30 0,1 100,-50 l 50,-25
+ a25,75 -30 0,1 100,-50 l 50,-25
+ a25,100 -30 0,1 100,-50 l 50,-25"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"/>
+ </group>
+
+ <group>
+ <path
+ android:name="pie2"
+ android:pathData="M200,350 l 50,-25
+ a25,12 -30 0,1 100,-50 l 50,-25
+ a25,25 -30 0,1 100,-50 l 50,-25
+ a25,37 -30 0,1 100,-50 l 50,-25
+ a25,50 -30 0,1 100,-50 l 50,-25"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="20"
+ android:pivotX="90"
+ android:pivotY="100"/>
+
+ </group>
+ <animation android:sequence="pie1,pie2"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml
new file mode 100644
index 0000000..6bc946f
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml
@@ -0,0 +1,48 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="500"
+ android:viewportHeight="400"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:fill="#ffffffff"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="1"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:fill="#ff440000"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="10"
+ android:rotation="180"
+ android:pivotX="250"
+ android:pivotY="200"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml
new file mode 100644
index 0000000..c9c8e8a
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml
@@ -0,0 +1,46 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="200"
+ android:viewportHeight="200"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M 100,10 v 180 M 10,100 h 180"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M 100,10 v 90 M 10,100 h 90"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="100"
+ android:pivotY="100"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml
new file mode 100644
index 0000000..9427652
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml
@@ -0,0 +1,46 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="1200"
+ android:viewportHeight="600"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M200,300 Q400,50 600,300 T1000,300"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M200,300 Q400,50 600,300 T1000,300"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="600"
+ android:pivotY="300"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml
new file mode 100644
index 0000000..83dfbd2
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml
@@ -0,0 +1,45 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="500"
+ android:viewportHeight="400"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:stroke="#FFFFFF00"
+ android:strokeWidth="10"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="250"
+ android:pivotY="200"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml
new file mode 100644
index 0000000..013254f
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml
@@ -0,0 +1,45 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="1000"
+ android:viewportHeight="800"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M10,300 Q400,50 600,300 T1000,300"
+ android:stroke="#FF00FFFF"
+ android:strokeWidth="40"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M10,300 Q400,550 600,300 T1000,300"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="60"
+ android:pivotX="90"
+ android:pivotY="100"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml
new file mode 100644
index 0000000..aba7e5f
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml
@@ -0,0 +1,37 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="480"
+ android:viewportHeight="480"/>
+
+ <group>
+ <path
+ android:name="edit"
+ android:pathData="M406.667,180c0,0 -100 -100 -113.334 -113.333
+ c-13.333 -13.334 -33.333,0 -33.333,0l-160,160c0,0 -40,153.333 -40,173.333c0,13.333,13.333,13.333,13.333,13.333l173.334 -40
+ c0,0,146.666 -146.666,160 -160C420,200,406.667,180,406.667,180z M226.399,356.823L131.95,378.62l-38.516 -38.522
+ c7.848 -34.675,20.152 -82.52,23.538 -95.593l3.027,2.162l106.667,106.666L226.399,356.823z"
+ android:stroke="#FF000000"
+ android:fill="#FF00FFFF"
+ android:strokeWidth="10"/>
+ </group>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml
new file mode 100644
index 0000000..8897181
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.813995,9.936001l-3.75,-3.75L3.0,17.25zM20.707,7.0429993c0.391,-0.391 0.391,-1.023 0.0,-1.414l-2.336,-2.336c-0.391,-0.391 -1.023,-0.391 -1.414,0.0l-1.832,1.832l3.75,3.75L20.707,7.0429993z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml
new file mode 100644
index 0000000..2c7ebbd
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0,-0.896 2.0,-2.0l0.0,-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0,-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0,-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml
new file mode 100644
index 0000000..e4cf78c
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67,-1.732 -2.547,-3.0 -4.5,-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207,-5.242 9.0,-7.971 9.0,-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml
new file mode 100644
index 0000000..cec12ba
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml
@@ -0,0 +1,33 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M11.994999,2.0C6.4679985,2.0 2.0,6.4780006 2.0,12.0s4.468,10.0 9.995,10.0S22.0,17.522 22.0,12.0S17.521,2.0 11.994999,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.582 -8.0,-8.0s3.58,-8.0 8.0,-8.0s8.0,3.582 8.0,8.0S16.419998,20.0 12.0,20.0z"
+ android:fillOpacity="0.9"
+ />
+<path
+ android:pathData="M12.5,6.0l-1.5,0.0 0.0,7.0 5.3029995,3.1819992 0.75,-1.249999 -4.5529995,-2.7320004z"
+ android:fillOpacity="0.9"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml
new file mode 100644
index 0000000..5fe1fb6
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M19.429,12.975998c0.042,-0.32 0.07,-0.645 0.07,-0.976s-0.029,-0.655 -0.07,-0.976l2.113,-1.654c0.188,-0.151 0.243,-0.422 0.118,-0.639l-2.0,-3.463c-0.125,-0.217 -0.386,-0.304 -0.612,-0.218l-2.49,1.004c-0.516,-0.396 -1.081,-0.731 -1.69,-0.984l-0.375,-2.648C14.456,2.1829987 14.25,2.0 14.0,2.0l-4.0,0.0C9.75,2.0 9.544,2.1829987 9.506,2.422001L9.131,5.0699997C8.521,5.322998 7.957,5.6570015 7.44,6.054001L4.952,5.0509987C4.726,4.965 4.464,5.052002 4.34,5.269001l-2.0,3.463C2.2150002,8.947998 2.27,9.219002 2.4580002,9.369999l2.112,1.653C4.528,11.344002 4.5,11.668999 4.5,12.0s0.029,0.656 0.071,0.977L2.4580002,14.630001c-0.188,0.151 -0.243,0.422 -0.118,0.639l2.0,3.463c0.125,0.217 0.386,0.304 0.612,0.218l2.489,-1.004c0.516,0.396 1.081,0.731 1.69,0.984l0.375,2.648C9.544,21.817001 9.75,22.0 10.0,22.0l4.0,0.0c0.25,0.0 0.456,-0.183 0.494,-0.422l0.375,-2.648c0.609,-0.253 1.174,-0.588 1.689,-0.984l2.49,1.004c0.226,0.086 0.487,-0.001 0.612,-0.218l2.0,-3.463c0.125,-0.217 0.07,-0.487 -0.118,-0.639L19.429,12.975998zM12.0,16.0c-2.21,0.0 -4.0,-1.791 -4.0,-4.0c0.0,-2.21 1.79,-4.0 4.0,-4.0c2.208,0.0 4.0,1.79 4.0,4.0C16.0,14.209 14.208,16.0 12.0,16.0z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test01.xml b/tests/DynamicDrawableTest/res/drawable/vector_test01.xml
new file mode 100644
index 0000000..6beb9d8
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_test01.xml
@@ -0,0 +1,31 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="128dp"
+android:height="128dp"/>
+
+ <viewport android:viewportWidth="512"
+ android:viewportHeight="512"/>
+
+<group>
+<path
+ android:name="002b"
+ android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0t-200,299"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="4"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test02.xml b/tests/DynamicDrawableTest/res/drawable/vector_test02.xml
new file mode 100644
index 0000000..2c1a28e
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_test02.xml
@@ -0,0 +1,31 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="128dp"
+android:height="128dp"/>
+
+ <viewport android:viewportWidth="512"
+ android:viewportHeight="512"/>
+
+<group>
+<path
+ android:name="002b"
+ android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0T-200,299"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="4"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/values/strings.xml b/tests/DynamicDrawableTest/res/values/strings.xml
new file mode 100644
index 0000000..64163c2
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+</resources>
diff --git a/tests/DynamicDrawableTest/res/values/styles.xml b/tests/DynamicDrawableTest/res/values/styles.xml
new file mode 100644
index 0000000..460c0db
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/values/styles.xml
@@ -0,0 +1,16 @@
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+</resources>
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
new file mode 100644
index 0000000..1060d19
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.test.dynamic;
+
+import android.app.Activity;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.GridLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorCheckbox extends Activity {
+ private static final String LOGCAT = "VectorDrawable1";
+ int[] icon = {
+ R.drawable.vector_drawable01,
+ R.drawable.vector_drawable02,
+ R.drawable.vector_drawable03,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable05,
+ R.drawable.vector_drawable06,
+ R.drawable.vector_drawable07,
+ R.drawable.vector_drawable08,
+ R.drawable.vector_drawable09,
+ R.drawable.vector_drawable10,
+ R.drawable.vector_drawable11,
+ R.drawable.vector_drawable12,
+ R.drawable.vector_drawable13,
+ R.drawable.vector_drawable14,
+ R.drawable.vector_drawable15,
+ R.drawable.vector_drawable16,
+ R.drawable.vector_drawable17,
+ R.drawable.vector_drawable18,
+ R.drawable.vector_drawable19,
+ R.drawable.vector_drawable20
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ GridLayout container = new GridLayout(this);
+ container.setColumnCount(5);
+ container.setBackgroundColor(0xFF888888);
+ final Button []bArray = new Button[icon.length];
+
+ for (int i = 0; i < icon.length; i++) {
+ CheckBox checkBox = new CheckBox(this);
+ bArray[i] = checkBox;
+ checkBox.setWidth(200);
+ checkBox.setWidth(200);
+ checkBox.setButtonDrawable(icon[i]);
+ container.addView(checkBox);
+ }
+ setContentView(container);
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
new file mode 100644
index 0000000..0ae4b6d
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.test.dynamic;
+
+import android.app.Activity;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.GridLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawable01 extends Activity implements View.OnClickListener {
+ private static final String LOGCAT = "VectorDrawable1";
+ int[] icon = {
+ R.drawable.vector_drawable01,
+ R.drawable.vector_drawable02,
+ R.drawable.vector_drawable03,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable05,
+ R.drawable.vector_drawable06,
+ R.drawable.vector_drawable07,
+ R.drawable.vector_drawable08,
+ R.drawable.vector_drawable09,
+ R.drawable.vector_drawable10,
+ R.drawable.vector_drawable11,
+ R.drawable.vector_drawable12,
+ R.drawable.vector_drawable13,
+ R.drawable.vector_drawable14,
+ R.drawable.vector_drawable15,
+ R.drawable.vector_drawable16,
+ R.drawable.vector_drawable17,
+ R.drawable.vector_drawable18,
+ R.drawable.vector_drawable19,
+ R.drawable.vector_drawable20
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ GridLayout container = new GridLayout(this);
+ container.setColumnCount(5);
+ container.setBackgroundColor(0xFF888888);
+ final Button []bArray = new Button[icon.length];
+
+ for (int i = 0; i < icon.length; i++) {
+ Button button = new Button(this);
+ bArray[i] = button;
+ button.setWidth(200);
+ button.setWidth(200);
+ button.setBackgroundResource(icon[i]);
+ container.addView(button);
+ button.setOnClickListener(this);
+ }
+ Button b = new Button(this);
+ b.setText("Run All");
+ b.setOnClickListener(new View.OnClickListener(){
+
+ @Override
+ public void onClick(View v) {
+ for (int i = 0; i < bArray.length; i++) {
+ VectorDrawable d = (VectorDrawable) bArray[i].getBackground();
+ d.start();
+ }
+ }});
+ container.addView(b);
+ setContentView(container);
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ VectorDrawable d = (VectorDrawable) v.getBackground();
+ d.start();
+ }
+
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
new file mode 100644
index 0000000..a00bc5e
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.test.dynamic;
+
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawableDupPerf extends VectorDrawablePerformance {
+ {
+ icon = new int[]{
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ };
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
new file mode 100644
index 0000000..9e8ea75
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.test.dynamic;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Button;
+import android.widget.GridLayout;
+import android.widget.ScrollView;
+import java.text.DecimalFormat;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawablePerformance extends Activity implements View.OnClickListener {
+ private static final String LOGCAT = "VectorDrawable1";
+ protected int[] icon = {
+ R.drawable.vector_drawable01,
+ R.drawable.vector_drawable02,
+ R.drawable.vector_drawable03,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable05,
+ R.drawable.vector_drawable06,
+ R.drawable.vector_drawable07,
+ R.drawable.vector_drawable08,
+ R.drawable.vector_drawable09,
+ R.drawable.vector_drawable10,
+ R.drawable.vector_drawable11,
+ R.drawable.vector_drawable12,
+ R.drawable.vector_drawable13,
+ R.drawable.vector_drawable14,
+ R.drawable.vector_drawable15,
+ R.drawable.vector_drawable16,
+ R.drawable.vector_drawable17,
+ R.drawable.vector_drawable18,
+ R.drawable.vector_drawable19,
+ R.drawable.vector_drawable20
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ScrollView scrollView = new ScrollView(this);
+ GridLayout container = new GridLayout(this);
+ scrollView.addView(container);
+ container.setColumnCount(5);
+ Resources res = this.getResources();
+ container.setBackgroundColor(0xFF888888);
+ VectorDrawable []d = new VectorDrawable[icon.length];
+ long time = android.os.SystemClock.elapsedRealtimeNanos();
+ for (int i = 0; i < icon.length; i++) {
+ d[i] = VectorDrawable.create(res,icon[i]);
+ }
+ time = android.os.SystemClock.elapsedRealtimeNanos()-time;
+ TextView t = new TextView(this);
+ DecimalFormat df = new DecimalFormat("#.##");
+ t.setText("avgL=" + df.format(time / (icon.length * 1000000.)) + " ms");
+ t.setBackgroundColor(0xFF000000);
+ container.addView(t);
+ time = android.os.SystemClock.elapsedRealtimeNanos();
+ for (int i = 0; i < icon.length; i++) {
+ Button button = new Button(this);
+ button.setWidth(200);
+ button.setWidth(200);
+ button.setBackgroundResource(icon[i]);
+ container.addView(button);
+ button.setOnClickListener(this);
+ }
+ setContentView(scrollView);
+ time = android.os.SystemClock.elapsedRealtimeNanos()-time;
+ t = new TextView(this);
+ t.setText("avgS=" + df.format(time / (icon.length * 1000000.)) + " ms");
+ t.setBackgroundColor(0xFF000000);
+ container.addView(t);
+ }
+
+ @Override
+ public void onClick(View v) {
+ VectorDrawable d = (VectorDrawable) v.getBackground();
+ d.start();
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
new file mode 100644
index 0000000..9d3eded
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.test.dynamic;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Button;
+import android.widget.GridLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawableStaticPerf extends VectorDrawablePerformance {
+ {
+ icon = new int[]{
+ R.drawable.vector_icon_create,
+ R.drawable.vector_icon_delete,
+ R.drawable.vector_icon_heart,
+ R.drawable.vector_icon_schedule,
+ R.drawable.vector_icon_settings,
+ };
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
new file mode 100644
index 0000000..704d3d7
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.dynamic;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings("UnusedDeclaration")
+public class VectorDrawableTest extends android.app.ListActivity {
+ private static final String EXTRA_PATH = "com.android.test.dynamic.Path";
+ private static final String CATEGORY_HWUI_TEST = "com.android.test.dynamic.TEST";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = getIntent();
+ String path = intent.getStringExtra("com.android.test.hwui.Path");
+
+ if (path == null) {
+ path = "";
+ }
+
+ setListAdapter(new SimpleAdapter(this, getData(path),
+ android.R.layout.simple_list_item_1, new String[] { "title" },
+ new int[] { android.R.id.text1 }));
+ getListView().setTextFilterEnabled(true);
+ }
+
+ protected List<Map<String, Object>> getData(String prefix) {
+ List<Map<String, Object>> myData = new ArrayList<Map<String, Object>>();
+
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(CATEGORY_HWUI_TEST);
+
+ PackageManager pm = getPackageManager();
+ List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
+
+ if (null == list)
+ return myData;
+
+ String[] prefixPath;
+ String prefixWithSlash = prefix;
+
+ if (prefix.equals("")) {
+ prefixPath = null;
+ } else {
+ prefixPath = prefix.split("/");
+ prefixWithSlash = prefix + "/";
+ }
+
+ int len = list.size();
+
+ Map<String, Boolean> entries = new HashMap<String, Boolean>();
+
+ for (int i = 0; i < len; i++) {
+ ResolveInfo info = list.get(i);
+ CharSequence labelSeq = info.loadLabel(pm);
+ String label = labelSeq != null
+ ? labelSeq.toString()
+ : info.activityInfo.name;
+
+ if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) {
+
+ String[] labelPath = label.split("/");
+
+ String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
+
+ if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
+ addItem(myData, nextLabel, activityIntent(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name));
+ } else {
+ if (entries.get(nextLabel) == null) {
+ addItem(myData, nextLabel, browseIntent(prefix.equals("") ?
+ nextLabel : prefix + "/" + nextLabel));
+ entries.put(nextLabel, true);
+ }
+ }
+ }
+ }
+
+ Collections.sort(myData, sDisplayNameComparator);
+
+ return myData;
+ }
+
+ private final static Comparator<Map<String, Object>> sDisplayNameComparator =
+ new Comparator<Map<String, Object>>() {
+ private final Collator collator = Collator.getInstance();
+
+ public int compare(Map<String, Object> map1, Map<String, Object> map2) {
+ return collator.compare(map1.get("title"), map2.get("title"));
+ }
+ };
+
+ protected Intent activityIntent(String pkg, String componentName) {
+ Intent result = new Intent();
+ result.setClassName(pkg, componentName);
+ return result;
+ }
+
+ protected Intent browseIntent(String path) {
+ Intent result = new Intent();
+ result.setClass(this, VectorDrawableTest.class);
+ result.putExtra(EXTRA_PATH, path);
+ return result;
+ }
+
+ protected void addItem(List<Map<String, Object>> data, String name, Intent intent) {
+ Map<String, Object> temp = new HashMap<String, Object>();
+ temp.put("title", name);
+ temp.put("intent", intent);
+ data.add(temp);
+ }
+
+ @Override
+ @SuppressWarnings({ "unchecked", "UnusedParameters" })
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position);
+
+ Intent intent = (Intent) map.get("intent");
+ startActivity(intent);
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
new file mode 100644
index 0000000..3430192
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.test.dynamic;
+
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorPathChecking extends VectorDrawablePerformance {
+ {
+ icon = new int[]{
+ R.drawable.vector_test01,
+ R.drawable.vector_test02
+ };
+ }
+}
diff --git a/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java b/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java
index b690c45..93aa555 100644
--- a/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java
@@ -16,7 +16,7 @@
package com.android.framework.permission.tests;
-import junit.framework.TestCase;
+import android.app.PackageInstallObserver;
import android.content.pm.PackageManager;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -68,10 +68,14 @@ public class PmPermissionsTests extends AndroidTestCase {
* This test verifies that PackageManger.installPackage enforces permission
* android.permission.INSTALL_PACKAGES
*/
+ private class TestInstallObserver extends PackageInstallObserver {
+ }
+
@SmallTest
public void testInstallPackage() {
+ TestInstallObserver observer = new TestInstallObserver();
try {
- mPm.installPackage(null, null, 0, null);
+ mPm.installPackage(null, observer, 0, null);
fail("PackageManager.installPackage" +
"did not throw SecurityException as expected");
} catch (SecurityException e) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
index 53e1640..a2a8aa9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
@@ -18,6 +18,7 @@ package com.android.layoutlib.bridge.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import android.util.SparseArray;
@@ -59,10 +60,8 @@ public class SparseWeakArray<E> {
* number of mappings.
*/
public SparseWeakArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
-
- mKeys = new long[initialCapacity];
- mValues = new WeakReference[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedLongArray(initialCapacity);
+ mValues = new WeakReference[mKeys.length];
mSize = 0;
}
@@ -142,18 +141,6 @@ public class SparseWeakArray<E> {
mGarbage = false;
mSize = o;
-
- int newSize = ArrayUtils.idealLongArraySize(mSize);
- if (newSize < mKeys.length) {
- long[] nkeys = new long[newSize];
- WeakReference<?>[] nvalues = new WeakReference[newSize];
-
- System.arraycopy(mKeys, 0, nkeys, 0, newSize);
- System.arraycopy(mValues, 0, nvalues, 0, newSize);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
}
/**
@@ -182,28 +169,8 @@ public class SparseWeakArray<E> {
i = ~binarySearch(mKeys, 0, mSize, key);
}
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealLongArraySize(mSize + 1);
-
- long[] nkeys = new long[n];
- WeakReference<?>[] nvalues = new WeakReference[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = new WeakReference(value);
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, new WeakReference(value));
mSize++;
}
}
@@ -321,24 +288,9 @@ public class SparseWeakArray<E> {
gc();
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealLongArraySize(pos + 1);
-
- long[] nkeys = new long[n];
- WeakReference<?>[] nvalues = new WeakReference[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = new WeakReference(value);
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, new WeakReference(value));
+ mSize++;
}
private boolean hasReclaimedRefs() {
diff --git a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl b/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
new file mode 100644
index 0000000..2b1601b
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.hotspot;
+
+/**
+ * Interface that allows controlling and querying Hotspot connectivity.
+ *
+ * {@hide}
+ */
+interface IWifiHotspotManager
+{
+ void test();
+}
+
diff --git a/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java b/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java
new file mode 100644
index 0000000..ac15017
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.hotspot;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * TODO: doc
+ */
+public class WifiHotspotManager {
+
+ private static final String TAG = "WifiHotspotManager";
+
+ private Context mContext;
+ IWifiHotspotManager mService;
+
+ public WifiHotspotManager(Context context, IWifiHotspotManager service) {
+ mContext = context;
+ mService = service;
+ }
+
+ public void test() {
+ try{
+ Log.d(TAG, "test()");
+ mService.test();
+ }
+ catch (RemoteException e) {
+ Log.e(TAG, "test() exception");
+ e.printStackTrace();
+ }
+ }
+}