summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt60
-rw-r--r--api/removed.txt20
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java23
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java68
-rw-r--r--core/java/android/animation/ObjectAnimator.java6
-rw-r--r--core/java/android/app/ActivityManager.java14
-rw-r--r--core/java/android/app/ActivityManagerNative.java6
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/app/Notification.java63
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java50
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl7
-rw-r--r--core/java/android/content/ContentProvider.java5
-rw-r--r--core/java/android/content/Intent.java7
-rw-r--r--core/java/android/hardware/hdmi/HdmiRecordListener.java12
-rw-r--r--core/java/android/hardware/hdmi/HdmiTvClient.java12
-rw-r--r--core/java/android/hardware/hdmi/IHdmiRecordListener.aidl16
-rw-r--r--core/java/android/net/ConnectivityManager.java130
-rw-r--r--core/java/android/net/DhcpResults.java4
-rw-r--r--core/java/android/net/IConnectivityManager.aidl2
-rw-r--r--core/java/android/net/NetworkCapabilities.java6
-rw-r--r--core/java/android/net/NetworkScoreManager.java19
-rw-r--r--core/java/android/net/NetworkScorerAppManager.java6
-rw-r--r--core/java/android/net/StaticIpConfiguration.java1
-rw-r--r--core/java/android/os/Debug.java37
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java12
-rw-r--r--core/java/android/service/trust/ITrustAgentService.aidl4
-rw-r--r--core/java/android/service/trust/ITrustAgentServiceCallback.aidl2
-rw-r--r--core/java/android/service/trust/TrustAgentService.java92
-rwxr-xr-xcore/java/android/text/format/DateFormat.java68
-rw-r--r--core/java/android/text/format/Formatter.java21
-rw-r--r--core/java/android/transition/Transition.java6
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java12
-rw-r--r--core/java/android/view/Surface.java1
-rw-r--r--core/java/android/view/ViewRootImpl.java8
-rw-r--r--core/java/android/view/WindowManagerGlobal.java18
-rw-r--r--core/java/android/widget/DayPickerView.java6
-rw-r--r--core/java/android/widget/Toolbar.java11
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java16
-rw-r--r--core/java/com/android/internal/app/IntentForwarderActivity.java79
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java31
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp10
-rw-r--r--core/jni/android/graphics/NinePatch.cpp6
-rw-r--r--core/jni/android/graphics/Path.cpp6
-rw-r--r--core/jni/android_os_Debug.cpp8
-rw-r--r--core/res/AndroidManifest.xml9
-rw-r--r--core/res/res/drawable-hdpi/sym_def_app_icon.pngbin9397 -> 3418 bytes
-rw-r--r--core/res/res/drawable-mdpi/sym_def_app_icon.pngbin5237 -> 2206 bytes
-rw-r--r--core/res/res/drawable-xhdpi/sym_def_app_icon.pngbin14383 -> 4842 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/sym_def_app_icon.pngbin23909 -> 7718 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/sym_def_app_icon.pngbin0 -> 10486 bytes
-rw-r--r--core/res/res/mipmap-hdpi/sym_def_app_icon.pngbin8539 -> 3418 bytes
-rw-r--r--core/res/res/mipmap-mdpi/sym_def_app_icon.pngbin4607 -> 2206 bytes
-rw-r--r--core/res/res/mipmap-xhdpi/sym_def_app_icon.pngbin12887 -> 4842 bytes
-rw-r--r--core/res/res/mipmap-xxhdpi/sym_def_app_icon.pngbin21003 -> 7718 bytes
-rw-r--r--core/res/res/mipmap-xxxhdpi/sym_def_app_icon.pngbin0 -> 10486 bytes
-rw-r--r--core/res/res/values/arrays.xml9
-rw-r--r--core/res/res/values/attrs.xml2
-rw-r--r--core/res/res/values/colors.xml15
-rw-r--r--core/res/res/values/config.xml12
-rw-r--r--core/res/res/values/strings.xml20
-rw-r--r--core/res/res/values/styles_micro.xml8
-rw-r--r--core/res/res/values/symbols.xml9
-rw-r--r--core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java4
-rw-r--r--docs/html/about/about_toc.cs1
-rw-r--r--docs/html/about/dashboards/index.jd67
-rw-r--r--docs/html/about/versions/android-5.0-changes.jd527
-rw-r--r--docs/html/about/versions/android-5.0.jd260
-rw-r--r--docs/html/design/tv/index.jd10
-rw-r--r--docs/html/distribute/essentials/quality/tv.jd8
-rw-r--r--docs/html/distribute/googleplay/edu/start.jd2
-rw-r--r--docs/html/distribute/googleplay/googleplay_toc.cs12
-rw-r--r--docs/html/distribute/googleplay/guide.jd71
-rw-r--r--docs/html/distribute/googleplay/index.jd2
-rw-r--r--docs/html/distribute/googleplay/tv.jd320
-rw-r--r--docs/html/distribute/images/play_dev_guide.pngbin0 -> 220901 bytes
-rw-r--r--docs/html/distribute/images/play_dev_guide_b.jpgbin0 -> 45170 bytes
-rw-r--r--docs/html/google/auth/api-client.jd52
-rw-r--r--docs/html/images/emulator-wvga800l.pngbin97756 -> 0 bytes
-rw-r--r--docs/html/images/emulator.pngbin0 -> 67074 bytes
-rw-r--r--docs/html/images/emulator@2x.pngbin0 -> 199560 bytes
-rw-r--r--docs/html/images/games/game-controller-buttons_2x_crop.pngbin0 -> 46087 bytes
-rw-r--r--docs/html/images/gp-tv-opt-in.pngbin0 -> 27991 bytes
-rw-r--r--docs/html/images/gp-tv-process.pngbin0 -> 34302 bytes
-rw-r--r--docs/html/images/tools/as-attach.pngbin0 -> 475 bytes
-rw-r--r--docs/html/jd_collections.js20
-rw-r--r--docs/html/jd_extras.js13
-rw-r--r--docs/html/sdk/installing/studio-debug.jd22
-rw-r--r--docs/html/sdk/installing/studio.jd1
-rw-r--r--docs/html/tools/devices/emulator.jd4
-rw-r--r--docs/html/training/articles/security-ssl.jd35
-rw-r--r--docs/html/training/material/animations.jd8
-rw-r--r--docs/html/training/tv/discovery/index.jd3
-rw-r--r--docs/html/training/tv/games/index.jd6
-rw-r--r--docs/html/training/tv/index.jd7
-rw-r--r--docs/html/training/tv/playback/index.jd2
-rw-r--r--docs/html/training/tv/start/hardware.jd77
-rw-r--r--docs/html/training/tv/start/index.jd1
-rw-r--r--docs/html/training/tv/start/start.jd52
-rw-r--r--docs/html/training/tv/tif/index.jd2
-rw-r--r--docs/html/training/wearables/apps/bt-debugging.jd3
-rw-r--r--docs/html/training/wearables/data-layer/accessing.jd15
-rw-r--r--docs/html/tv/index.jd6
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java12
-rw-r--r--include/androidfw/ResourceTypes.h35
-rw-r--r--libs/androidfw/Android.mk34
-rw-r--r--libs/androidfw/ResourceTypes.cpp63
-rw-r--r--libs/androidfw/misc.cpp4
-rw-r--r--libs/androidfw/tests/Android.mk3
-rw-r--r--libs/hwui/Caches.h1
-rw-r--r--libs/hwui/DisplayList.cpp17
-rw-r--r--libs/hwui/DisplayListRenderer.cpp4
-rw-r--r--libs/hwui/DisplayListRenderer.h11
-rw-r--r--libs/hwui/PathTessellator.cpp2
-rw-r--r--libs/hwui/Program.cpp3
-rw-r--r--libs/hwui/RenderNode.cpp10
-rw-r--r--libs/hwui/ResourceCache.cpp6
-rw-r--r--libs/hwui/ResourceCache.h8
-rw-r--r--location/java/android/location/GpsClock.java1
-rw-r--r--media/java/android/media/AudioService.java217
-rw-r--r--media/java/android/media/MediaDrm.java14
-rw-r--r--media/java/android/media/MediaMetadata.java29
-rw-r--r--media/java/android/media/session/MediaController.java6
-rw-r--r--media/java/android/media/session/MediaSession.java68
-rw-r--r--media/java/android/media/session/PlaybackState.java36
-rw-r--r--media/java/android/media/tv/TvInputService.java20
-rw-r--r--media/java/android/service/media/MediaBrowserService.java1
-rw-r--r--media/jni/android_media_MediaDrm.cpp42
-rw-r--r--media/jni/audioeffect/android_media_AudioEffect.cpp20
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java2
-rw-r--r--packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java13
-rw-r--r--packages/SystemUI/res/anim/ic_invert_colors_disable_animation_cross_1.xml50
-rw-r--r--packages/SystemUI/res/anim/ic_invert_colors_disable_animation_icon.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_invert_colors_disable_animation_mask.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml24
-rw-r--r--packages/SystemUI/res/anim/ic_invert_colors_enable_animation_cross_1.xml50
-rw-r--r--packages/SystemUI/res/anim/ic_invert_colors_enable_animation_icon.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_invert_colors_enable_animation_mask.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml24
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml63
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml63
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_bottom.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_top.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrows.xml63
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device_1.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_bottom.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_top.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrows.xml63
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device_1.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_cross_1.xml50
-rw-r--r--packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_ic_signal_airplane.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_mask.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml24
-rw-r--r--packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_cross_1.xml50
-rw-r--r--packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_ic_signal_airplane.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_mask.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml24
-rw-r--r--packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_cross_1.xml50
-rw-r--r--packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_ic_signal_flashlight.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_mask.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml24
-rw-r--r--packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_cross_1.xml50
-rw-r--r--packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_ic_signal_flashlight.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_mask.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml24
-rw-r--r--packages/SystemUI/res/anim/ic_signal_location_disable_animation_cross_1.xml50
-rw-r--r--packages/SystemUI/res/anim/ic_signal_location_disable_animation_ic_signal_location.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_signal_location_disable_animation_mask.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml24
-rw-r--r--packages/SystemUI/res/anim/ic_signal_location_enable_animation_cross_1.xml50
-rw-r--r--packages/SystemUI/res/anim/ic_signal_location_enable_animation_ic_signal_location.xml33
-rw-r--r--packages/SystemUI/res/anim/ic_signal_location_enable_animation_mask.xml35
-rw-r--r--packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml24
-rw-r--r--packages/SystemUI/res/drawable/ic_invert_colors_disable.xml56
-rw-r--r--packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_invert_colors_enable.xml57
-rw-r--r--packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml (renamed from tests/VectorDrawableTest/res/drawable/ic_open_animation.xml)22
-rw-r--r--packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml62
-rw-r--r--packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml66
-rw-r--r--packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml62
-rw-r--r--packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml66
-rw-r--r--packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_airplane_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_airplane_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_flashlight_off.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_flashlight_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_inversion_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_inversion_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml24
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml57
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml58
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml57
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml58
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_location_disable.xml57
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_location_enable.xml58
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml31
-rw-r--r--packages/SystemUI/res/interpolator/ic_invert_colors_disable_cross_1_pathdata_interpolator.xml18
-rw-r--r--packages/SystemUI/res/interpolator/ic_invert_colors_enable_cross_1_pathdata_interpolator.xml18
-rw-r--r--packages/SystemUI/res/interpolator/ic_invert_colors_enable_mask_pathdata_interpolator.xml (renamed from tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_1.xml)6
-rw-r--r--packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.xml18
-rw-r--r--packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml18
-rw-r--r--packages/SystemUI/res/interpolator/ic_signal_airplane_disable_cross_1_pathdata_interpolator.xml18
-rw-r--r--packages/SystemUI/res/interpolator/ic_signal_airplane_enable_cross_1_pathdata_interpolator.xml18
-rw-r--r--packages/SystemUI/res/interpolator/ic_signal_airplane_enable_mask_pathdata_interpolator.xml (renamed from tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_3.xml)6
-rw-r--r--packages/SystemUI/res/interpolator/ic_signal_flashlight_enable_cross_1_pathdata_interpolator.xml (renamed from tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_2.xml)6
-rw-r--r--packages/SystemUI/res/interpolator/ic_signal_flashlight_enable_mask_pathdata_interpolator.xml (renamed from tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_1.xml)6
-rw-r--r--packages/SystemUI/res/interpolator/ic_signal_location_enable_cross_1_pathdata_interpolator.xml18
-rw-r--r--packages/SystemUI/res/interpolator/ic_signal_location_enable_mask_pathdata_interpolator.xml18
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/res/values/ids.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTile.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileView.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java114
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java12
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java77
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java199
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java335
-rw-r--r--services/core/java/com/android/server/LockSettingsStorage.java307
-rw-r--r--services/core/java/com/android/server/NativeDaemonConnector.java3
-rw-r--r--services/core/java/com/android/server/NetworkScoreService.java25
-rw-r--r--services/core/java/com/android/server/PersistentDataBlockService.java17
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java24
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java150
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityStack.java15
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java3
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java16
-rw-r--r--services/core/java/com/android/server/connectivity/PermissionMonitor.java4
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java24
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java37
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java50
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java67
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java16
-rw-r--r--services/core/java/com/android/server/hdmi/OneTouchRecordAction.java6
-rw-r--r--services/core/java/com/android/server/hdmi/TimerRecordingAction.java12
-rw-r--r--services/core/java/com/android/server/notification/ConditionProviders.java35
-rw-r--r--services/core/java/com/android/server/notification/DowntimeConditionProvider.java46
-rw-r--r--services/core/java/com/android/server/notification/NextAlarmConditionProvider.java353
-rw-r--r--services/core/java/com/android/server/notification/ZenLog.java4
-rw-r--r--services/core/java/com/android/server/pm/CrossProfileIntentFilter.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java16
-rw-r--r--services/core/java/com/android/server/trust/TrustAgentWrapper.java22
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java7
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java6
-rw-r--r--services/core/java/com/android/server/wm/AppWindowAnimator.java54
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java124
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java33
-rw-r--r--services/core/jni/com_android_server_location_GpsLocationProvider.cpp1
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java161
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsDatabase.java1
-rw-r--r--telecomm/java/android/telecom/Conference.java7
-rw-r--r--telecomm/java/android/telecom/Connection.java9
-rw-r--r--telecomm/java/android/telecom/DisconnectCause.java20
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java24
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl6
-rw-r--r--telephony/java/android/telephony/SubInfoRecord.java234
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java2
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java2
-rw-r--r--tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml86
-rw-r--r--tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml17
-rw-r--r--tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml48
-rw-r--r--tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml74
-rw-r--r--tests/VectorDrawableTest/res/drawable/ic_open.xml56
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml16
-rw-r--r--tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml16
-rw-r--r--tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java1
-rw-r--r--tools/aapt/AaptConfig.cpp19
-rw-r--r--tools/aapt/AaptConfig.h6
-rw-r--r--tools/aapt/AaptUtil.h40
-rw-r--r--tools/aapt/AaptXml.cpp4
-rw-r--r--tools/aapt/Android.mk56
-rw-r--r--tools/aapt/CacheUpdater.h4
-rw-r--r--tools/aapt/Main.cpp4
-rw-r--r--tools/aapt/Resource.cpp79
-rw-r--r--tools/aapt/ResourceTable.cpp42
-rw-r--r--tools/aapt/ResourceTable.h13
-rw-r--r--tools/aapt/SourcePos.cpp6
-rw-r--r--tools/aapt/SourcePos.h2
-rw-r--r--tools/aapt/StringPool.cpp16
-rw-r--r--tools/aapt/StringPool.h5
-rw-r--r--tools/aapt/Symbol.h95
-rw-r--r--tools/aapt/XMLNode.cpp18
-rw-r--r--tools/layoutlib/bridge/src/android/view/WindowCallback.java131
-rw-r--r--tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java32
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java10
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java38
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java251
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java351
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java11
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java5
-rw-r--r--tools/split-select/Abi.cpp78
-rw-r--r--tools/split-select/Abi.h32
-rw-r--r--tools/split-select/Android.mk7
-rw-r--r--tools/split-select/Grouper.cpp26
-rw-r--r--tools/split-select/Grouper_test.cpp70
-rw-r--r--tools/split-select/Main.cpp5
-rw-r--r--tools/split-select/RuleGenerator.cpp8
-rw-r--r--tools/split-select/RuleGenerator_test.cpp36
-rw-r--r--tools/split-select/SplitDescription.cpp28
-rw-r--r--tools/split-select/SplitDescription.h1
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java2
374 files changed, 9139 insertions, 3159 deletions
diff --git a/api/current.txt b/api/current.txt
index 6851bbf..8b577dd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4798,7 +4798,9 @@ package android.app {
method public int getCustomSizePreset();
method public android.app.PendingIntent getDisplayIntent();
method public int getGravity();
+ method public boolean getHintAvoidBackgroundClipping();
method public boolean getHintHideIcon();
+ method public int getHintScreenTimeout();
method public boolean getHintShowBackgroundOnly();
method public java.util.List<android.app.Notification> getPages();
method public boolean getStartScrollBottom();
@@ -4811,9 +4813,13 @@ package android.app {
method public android.app.Notification.WearableExtender setCustomSizePreset(int);
method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
method public android.app.Notification.WearableExtender setGravity(int);
+ method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
+ method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
method public android.app.Notification.WearableExtender setStartScrollBottom(boolean);
+ field public static final int SCREEN_TIMEOUT_LONG = -1; // 0xffffffff
+ field public static final int SCREEN_TIMEOUT_SHORT = 0; // 0x0
field public static final int SIZE_DEFAULT = 0; // 0x0
field public static final int SIZE_FULL_SCREEN = 5; // 0x5
field public static final int SIZE_LARGE = 4; // 0x4
@@ -5317,6 +5323,7 @@ package android.app.admin {
method public boolean getScreenCaptureDisabled(android.content.ComponentName);
method public boolean getStorageEncryption(android.content.ComponentName);
method public int getStorageEncryptionStatus();
+ method public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName);
method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
method public boolean installCaCert(android.content.ComponentName, byte[]);
@@ -5365,6 +5372,7 @@ package android.app.admin {
method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
+ method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
method public void uninstallAllUserCaCerts(android.content.ComponentName);
@@ -16304,6 +16312,7 @@ package android.media.session {
method public void setPlaybackToRemote(android.media.VolumeProvider);
method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>);
method public void setQueueTitle(java.lang.CharSequence);
+ method public void setRatingType(int);
method public void setSessionActivity(android.app.PendingIntent);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
@@ -16362,6 +16371,7 @@ package android.media.session {
method public long getBufferedPosition();
method public java.util.List<android.media.session.PlaybackState.CustomAction> getCustomActions();
method public java.lang.CharSequence getErrorMessage();
+ method public android.os.Bundle getExtras();
method public long getLastPositionUpdateTime();
method public float getPlaybackSpeed();
method public long getPosition();
@@ -16406,6 +16416,7 @@ package android.media.session {
method public android.media.session.PlaybackState.Builder setActiveQueueItemId(long);
method public android.media.session.PlaybackState.Builder setBufferedPosition(long);
method public android.media.session.PlaybackState.Builder setErrorMessage(java.lang.CharSequence);
+ method public android.media.session.PlaybackState.Builder setExtras(android.os.Bundle);
method public android.media.session.PlaybackState.Builder setState(int, long, float, long);
method public android.media.session.PlaybackState.Builder setState(int, long, float);
}
@@ -16885,9 +16896,11 @@ package android.net {
method public boolean isDefaultNetworkActive();
method public static boolean isNetworkTypeValid(int);
method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+ method public void releaseNetworkRequest(android.app.PendingIntent);
method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public void reportBadNetwork(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+ method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
method public deprecated boolean requestRouteToHost(int, int);
method public deprecated void setNetworkPreference(int);
method public static boolean setProcessDefaultNetwork(android.net.Network);
@@ -16900,6 +16913,8 @@ package android.net {
field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
+ field public static final java.lang.String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
+ field public static final java.lang.String EXTRA_NETWORK_REQUEST_NETWORK_REQUEST = "networkRequestNetworkRequest";
field public static final java.lang.String EXTRA_NETWORK_TYPE = "networkType";
field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
@@ -28095,6 +28110,7 @@ package android.telecom {
method public final int getCapabilities();
method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
method public final java.util.List<android.telecom.Connection> getConnections();
+ method public final android.telecom.DisconnectCause getDisconnectCause();
method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle();
method public android.telecom.Connection getPrimaryConnection();
method public final int getState();
@@ -28214,6 +28230,7 @@ package android.telecom {
method public void writeToParcel(android.os.Parcel, int);
field public static final int BUSY = 7; // 0x7
field public static final int CANCELED = 4; // 0x4
+ field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
field public static final int ERROR = 1; // 0x1
field public static final int LOCAL = 2; // 0x2
@@ -28391,9 +28408,12 @@ package android.telecom {
method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
method public void cancelMissedCallsNotification();
method public void clearAccounts();
+ method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
method public android.telecom.PhoneAccountHandle getConnectionManager();
+ method public android.telecom.PhoneAccountHandle getDefaultOutgoingPhoneAccount(java.lang.String);
method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
+ method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
method public boolean handleMmi(java.lang.String);
method public boolean handleMmi(android.telecom.PhoneAccountHandle, java.lang.String);
method public boolean hasMultipleCallCapableAccounts();
@@ -28849,26 +28869,20 @@ package android.telephony {
}
public class SubInfoRecord implements android.os.Parcelable {
- ctor public SubInfoRecord();
- ctor public SubInfoRecord(int, java.lang.String, int, java.lang.String, int, int, java.lang.String, int, int, int[], int, int);
method public int describeContents();
method public int getColor();
- method public android.graphics.drawable.BitmapDrawable getIconDrawable();
- method public java.lang.String getLabel();
+ method public int getDataRoaming();
+ method public java.lang.CharSequence getDisplayName();
+ method public java.lang.String getIccId();
+ method public android.graphics.drawable.BitmapDrawable getIcon();
+ method public int getMcc();
+ method public int getMnc();
+ method public int getNameSource();
+ method public java.lang.String getNumber();
+ method public int getSimSlotIndex();
+ method public int getSubscriptionId();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.SubInfoRecord> CREATOR;
- field public int color;
- field public int dataRoaming;
- field public java.lang.String displayName;
- field public int displayNumberFormat;
- field public java.lang.String iccId;
- field public int mcc;
- field public int mnc;
- field public int nameSource;
- field public java.lang.String number;
- field public int[] simIconRes;
- field public int slotId;
- field public int subId;
}
public class SubscriptionManager implements android.provider.BaseColumns {
@@ -30278,19 +30292,6 @@ package android.text.format {
method public static java.text.DateFormat getMediumDateFormat(android.content.Context);
method public static java.text.DateFormat getTimeFormat(android.content.Context);
method public static boolean is24HourFormat(android.content.Context);
- field public static final deprecated char AM_PM = 97; // 0x0061 'a'
- field public static final deprecated char CAPITAL_AM_PM = 65; // 0x0041 'A'
- field public static final deprecated char DATE = 100; // 0x0064 'd'
- field public static final deprecated char DAY = 69; // 0x0045 'E'
- field public static final deprecated char HOUR = 104; // 0x0068 'h'
- field public static final deprecated char HOUR_OF_DAY = 107; // 0x006b 'k'
- field public static final deprecated char MINUTE = 109; // 0x006d 'm'
- field public static final deprecated char MONTH = 77; // 0x004d 'M'
- field public static final deprecated char QUOTE = 39; // 0x0027 '\''
- field public static final deprecated char SECONDS = 115; // 0x0073 's'
- field public static final deprecated char STANDALONE_MONTH = 76; // 0x004c 'L'
- field public static final deprecated char TIME_ZONE = 122; // 0x007a 'z'
- field public static final deprecated char YEAR = 121; // 0x0079 'y'
}
public class DateUtils {
@@ -33412,7 +33413,6 @@ package android.view {
method public int describeContents();
method public boolean isValid();
method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException;
- method public android.graphics.Canvas lockHardwareCanvas();
method public void readFromParcel(android.os.Parcel);
method public void release();
method public deprecated void unlockCanvas(android.graphics.Canvas);
diff --git a/api/removed.txt b/api/removed.txt
index 8972679..1b69ee8 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -22,6 +22,26 @@ package android.os {
}
+package android.text.format {
+
+ public class DateFormat {
+ field public static final deprecated char AM_PM = 97; // 0x0061 'a'
+ field public static final deprecated char CAPITAL_AM_PM = 65; // 0x0041 'A'
+ field public static final deprecated char DATE = 100; // 0x0064 'd'
+ field public static final deprecated char DAY = 69; // 0x0045 'E'
+ field public static final deprecated char HOUR = 104; // 0x0068 'h'
+ field public static final deprecated char HOUR_OF_DAY = 107; // 0x006b 'k'
+ field public static final deprecated char MINUTE = 109; // 0x006d 'm'
+ field public static final deprecated char MONTH = 77; // 0x004d 'M'
+ field public static final deprecated char QUOTE = 39; // 0x0027 '\''
+ field public static final deprecated char SECONDS = 115; // 0x0073 's'
+ field public static final deprecated char STANDALONE_MONTH = 76; // 0x004c 'L'
+ field public static final deprecated char TIME_ZONE = 122; // 0x007a 'z'
+ field public static final deprecated char YEAR = 121; // 0x0079 'y'
+ }
+
+}
+
package android.view {
public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index ba11a81..bc57030 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -417,7 +417,7 @@ public class Am extends BaseCommand {
} else if (opt.equals("--ei")) {
String key = nextArgRequired();
String value = nextArgRequired();
- intent.putExtra(key, Integer.valueOf(value));
+ intent.putExtra(key, Integer.decode(value));
} else if (opt.equals("--eu")) {
String key = nextArgRequired();
String value = nextArgRequired();
@@ -434,7 +434,7 @@ public class Am extends BaseCommand {
String[] strings = value.split(",");
int[] list = new int[strings.length];
for (int i = 0; i < strings.length; i++) {
- list[i] = Integer.valueOf(strings[i]);
+ list[i] = Integer.decode(strings[i]);
}
intent.putExtra(key, list);
} else if (opt.equals("--el")) {
@@ -477,8 +477,23 @@ public class Am extends BaseCommand {
hasIntentInfo = true;
} else if (opt.equals("--ez")) {
String key = nextArgRequired();
- String value = nextArgRequired();
- intent.putExtra(key, Boolean.valueOf(value));
+ String value = nextArgRequired().toLowerCase();
+ // Boolean.valueOf() results in false for anything that is not "true", which is
+ // error-prone in shell commands
+ boolean arg;
+ if ("true".equals(value) || "t".equals(value)) {
+ arg = true;
+ } else if ("false".equals(value) || "f".equals(value)) {
+ arg = false;
+ } else {
+ try {
+ arg = Integer.decode(value) != 0;
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException("Invalid boolean value: " + value);
+ }
+ }
+
+ intent.putExtra(key, arg);
} else if (opt.equals("-n")) {
String str = nextArgRequired();
ComponentName cn = ComponentName.unflattenFromString(str);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 1e1b33f..a9eaf29 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -24,11 +24,9 @@ import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
-import android.view.Display;
import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -620,18 +618,6 @@ public abstract class AccessibilityService extends Service {
}
}
- @Override
- public Object getSystemService(String name) {
- if (Context.WINDOW_SERVICE.equals(name)) {
- if (mWindowManager == null) {
- WindowManager wrapped = (WindowManager) super.getSystemService(name);
- mWindowManager = new LocalWindowManager(wrapped);
- }
- return mWindowManager;
- }
- return super.getSystemService(name);
- }
-
/**
* Implement to return the implementation of the internal accessibility
* service interface.
@@ -658,6 +644,9 @@ public abstract class AccessibilityService extends Service {
public void init(int connectionId, IBinder windowToken) {
mConnectionId = connectionId;
mWindowToken = windowToken;
+
+ // Let the window manager know about our shiny new token.
+ WindowManagerGlobal.getInstance().setDefaultToken(mWindowToken);
}
@Override
@@ -812,53 +801,4 @@ public abstract class AccessibilityService extends Service {
}
}
}
-
- private class LocalWindowManager implements WindowManager {
- private final WindowManager mImpl;
-
- private LocalWindowManager(WindowManager impl) {
- mImpl = impl;
- }
-
- @Override
- public Display getDefaultDisplay() {
- return mImpl.getDefaultDisplay();
- }
-
- @Override
- public void addView(View view, ViewGroup.LayoutParams params) {
- if (!(params instanceof WindowManager.LayoutParams)) {
- throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
- }
- WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
- if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
- && windowParams.token == null) {
- windowParams.token = mWindowToken;
- }
- mImpl.addView(view, params);
- }
-
- @Override
- public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
- if (!(params instanceof WindowManager.LayoutParams)) {
- throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
- }
- WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
- if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
- && windowParams.token == null) {
- windowParams.token = mWindowToken;
- }
- mImpl.updateViewLayout(view, params);
- }
-
- @Override
- public void removeViewImmediate(View view) {
- mImpl.removeViewImmediate(view);
- }
-
- @Override
- public void removeView(View view) {
- mImpl.removeView(view);
- }
- }
}
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 500634c..59daaab 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -885,7 +885,8 @@ public final class ObjectAnimator extends ValueAnimator {
}
/**
- * Sets the target object whose property will be animated by this animation
+ * Sets the target object whose property will be animated by this animation. If the
+ * animator has been started, it will be canceled.
*
* @param target The object being animated
*/
@@ -893,6 +894,9 @@ public final class ObjectAnimator extends ValueAnimator {
public void setTarget(@Nullable Object target) {
final Object oldTarget = getTarget();
if (oldTarget != target) {
+ if (isStarted()) {
+ cancel();
+ }
mTarget = target == null ? null : new WeakReference<Object>(target);
// New target should cause re-initialization prior to starting
mInitialized = false;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 37e8aa4..a285932 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1243,26 +1243,16 @@ public class ActivityManager {
}
/**
- * If set, the process of the root activity of the task will be killed
- * as part of removing the task.
- * @hide
- */
- public static final int REMOVE_TASK_KILL_PROCESS = 0x0001;
-
- /**
* Completely remove the given task.
*
* @param taskId Identifier of the task to be removed.
- * @param flags Additional operational flags. May be 0 or
- * {@link #REMOVE_TASK_KILL_PROCESS}.
* @return Returns true if the given task was found and removed.
*
* @hide
*/
- public boolean removeTask(int taskId, int flags)
- throws SecurityException {
+ public boolean removeTask(int taskId) throws SecurityException {
try {
- return ActivityManagerNative.getDefault().removeTask(taskId, flags);
+ return ActivityManagerNative.getDefault().removeTask(taskId);
} catch (RemoteException e) {
// System dead, we will be dead too soon!
return false;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 4e2ff0b..bc7114b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1884,8 +1884,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
{
data.enforceInterface(IActivityManager.descriptor);
int taskId = data.readInt();
- int fl = data.readInt();
- boolean result = removeTask(taskId, fl);
+ boolean result = removeTask(taskId);
reply.writeNoException();
reply.writeInt(result ? 1 : 0);
return true;
@@ -4778,12 +4777,11 @@ class ActivityManagerProxy implements IActivityManager
return result;
}
- public boolean removeTask(int taskId, int flags) throws RemoteException {
+ public boolean removeTask(int taskId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(taskId);
- data.writeInt(flags);
mRemote.transact(REMOVE_TASK_TRANSACTION, data, reply, 0);
reply.readException();
boolean result = reply.readInt() != 0;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index be26f30..efcb197 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -373,7 +373,7 @@ public interface IActivityManager extends IInterface {
public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
public int[] getRunningUserIds() throws RemoteException;
- public boolean removeTask(int taskId, int flags) throws RemoteException;
+ public boolean removeTask(int taskId) throws RemoteException;
public void registerProcessObserver(IProcessObserver observer) throws RemoteException;
public void unregisterProcessObserver(IProcessObserver observer) throws RemoteException;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 9849c51..c65f017 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4340,6 +4340,19 @@ public class Notification implements Parcelable
*/
public static final int SIZE_FULL_SCREEN = 5;
+ /**
+ * Sentinel value for use with {@link #setHintScreenTimeout} to keep the screen on for a
+ * short amount of time when this notification is displayed on the screen. This
+ * is the default value.
+ */
+ public static final int SCREEN_TIMEOUT_SHORT = 0;
+
+ /**
+ * Sentinel value for use with {@link #setHintScreenTimeout} to keep the screen on
+ * for a longer amount of time when this notification is displayed on the screen.
+ */
+ public static final int SCREEN_TIMEOUT_LONG = -1;
+
/** Notification extra which contains wearable extensions */
private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS";
@@ -4355,12 +4368,14 @@ public class Notification implements Parcelable
private static final String KEY_CUSTOM_SIZE_PRESET = "customSizePreset";
private static final String KEY_CUSTOM_CONTENT_HEIGHT = "customContentHeight";
private static final String KEY_GRAVITY = "gravity";
+ private static final String KEY_HINT_SCREEN_TIMEOUT = "hintScreenTimeout";
// Flags bitwise-ored to mFlags
private static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 0x1;
private static final int FLAG_HINT_HIDE_ICON = 1 << 1;
private static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2;
private static final int FLAG_START_SCROLL_BOTTOM = 1 << 3;
+ private static final int FLAG_HINT_AVOID_BACKGROUND_CLIPPING = 1 << 4;
// Default value for flags integer
private static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE;
@@ -4379,6 +4394,7 @@ public class Notification implements Parcelable
private int mCustomSizePreset = SIZE_DEFAULT;
private int mCustomContentHeight;
private int mGravity = DEFAULT_GRAVITY;
+ private int mHintScreenTimeout;
/**
* Create a {@link android.app.Notification.WearableExtender} with default
@@ -4414,6 +4430,7 @@ public class Notification implements Parcelable
SIZE_DEFAULT);
mCustomContentHeight = wearableBundle.getInt(KEY_CUSTOM_CONTENT_HEIGHT);
mGravity = wearableBundle.getInt(KEY_GRAVITY, DEFAULT_GRAVITY);
+ mHintScreenTimeout = wearableBundle.getInt(KEY_HINT_SCREEN_TIMEOUT);
}
}
@@ -4461,6 +4478,9 @@ public class Notification implements Parcelable
if (mGravity != DEFAULT_GRAVITY) {
wearableBundle.putInt(KEY_GRAVITY, mGravity);
}
+ if (mHintScreenTimeout != 0) {
+ wearableBundle.putInt(KEY_HINT_SCREEN_TIMEOUT, mHintScreenTimeout);
+ }
builder.getExtras().putBundle(EXTRA_WEARABLE_EXTENSIONS, wearableBundle);
return builder;
@@ -4480,6 +4500,7 @@ public class Notification implements Parcelable
that.mCustomSizePreset = this.mCustomSizePreset;
that.mCustomContentHeight = this.mCustomContentHeight;
that.mGravity = this.mGravity;
+ that.mHintScreenTimeout = this.mHintScreenTimeout;
return that;
}
@@ -4875,6 +4896,48 @@ public class Notification implements Parcelable
return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0;
}
+ /**
+ * Set a hint that this notification's background should not be clipped if possible.
+ * @param hintAvoidBackgroundClipping {@code true} to avoid clipping if possible.
+ * @return this object for method chaining
+ */
+ public WearableExtender setHintAvoidBackgroundClipping(
+ boolean hintAvoidBackgroundClipping) {
+ setFlag(FLAG_HINT_AVOID_BACKGROUND_CLIPPING, hintAvoidBackgroundClipping);
+ return this;
+ }
+
+ /**
+ * Get a hint that this notification's background should not be clipped if possible.
+ * @return {@code true} if it's ok if the background is clipped on the screen, false
+ * otherwise. The default value is {@code false} if this was never set.
+ */
+ public boolean getHintAvoidBackgroundClipping() {
+ return (mFlags & FLAG_HINT_AVOID_BACKGROUND_CLIPPING) != 0;
+ }
+
+ /**
+ * Set a hint that the screen should remain on for at least this duration when
+ * this notification is displayed on the screen.
+ * @param timeout The requested screen timeout in milliseconds. Can also be either
+ * {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}.
+ * @return this object for method chaining
+ */
+ public WearableExtender setHintScreenTimeout(int timeout) {
+ mHintScreenTimeout = timeout;
+ return this;
+ }
+
+ /**
+ * Get the duration, in milliseconds, that the screen should remain on for
+ * when this notification is displayed.
+ * @return the duration in milliseconds if > 0, or either one of the sentinel values
+ * {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}.
+ */
+ public int getHintScreenTimeout() {
+ return mHintScreenTimeout;
+ }
+
private void setFlag(int mask, boolean value) {
if (value) {
mFlags |= mask;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 74502fc..d3ff79d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -31,6 +31,7 @@ import android.content.pm.ResolveInfo;
import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.Handler;
+import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -40,6 +41,7 @@ import android.os.UserManager;
import android.provider.Settings;
import android.security.Credentials;
import android.service.restrictions.RestrictionsReceiver;
+import android.service.trust.TrustAgentService;
import android.util.Log;
import com.android.org.conscrypt.TrustedCertificateStore;
@@ -2604,25 +2606,29 @@ public class DevicePolicyManager {
}
/**
- * Sets a list of features to enable for a TrustAgent component. This is meant to be
- * used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which will disable all
- * trust agents but those with features enabled by this function call.
+ * Sets a list of configuration features to enable for a TrustAgent component. This is meant
+ * to be used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which disables all
+ * trust agents but those enabled by this function call. If flag
+ * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is not set, then this call has no effect.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call
- * this method; if it has not, a security exception will be thrown.
+ * this method; if not, a security exception will be thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param agent Which component to enable features for.
- * @param features List of features to enable. Consult specific TrustAgent documentation for
- * the feature list.
- * @hide
+ * @param target Component name of the agent to be enabled.
+ * @param options TrustAgent-specific feature bundle. If null for any admin, agent
+ * will be strictly disabled according to the state of the
+ * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} flag.
+ * <p>If {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is set and options is not null for all admins,
+ * then it's up to the TrustAgent itself to aggregate the values from all device admins.
+ * <p>Consult documentation for the specific TrustAgent to determine legal options parameters.
*/
- public void setTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
- List<String> features) {
+ public void setTrustAgentConfiguration(ComponentName admin, ComponentName target,
+ PersistableBundle options) {
if (mService != null) {
try {
- mService.setTrustAgentFeaturesEnabled(admin, agent, features, UserHandle.myUserId());
+ mService.setTrustAgentConfiguration(admin, target, options, UserHandle.myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2630,24 +2636,30 @@ public class DevicePolicyManager {
}
/**
- * Gets list of enabled features for the given TrustAgent component. If admin is
- * null, this will return the intersection of all features enabled for the given agent by all
- * admins.
+ * Gets configuration for the given trust agent based on aggregating all calls to
+ * {@link #setTrustAgentConfiguration(ComponentName, ComponentName, PersistableBundle)} for
+ * all device admins.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param agent Which component to get enabled features for.
- * @return List of enabled features.
- * @hide
+ * @return configuration for the given trust agent.
*/
- public List<String> getTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent) {
+ public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
+ ComponentName agent) {
+ return getTrustAgentConfiguration(admin, agent, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
+ ComponentName agent, int userHandle) {
if (mService != null) {
try {
- return mService.getTrustAgentFeaturesEnabled(admin, agent, UserHandle.myUserId());
+ return mService.getTrustAgentConfiguration(admin, agent, userHandle);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
- return new ArrayList<String>(); // empty list
+ return new ArrayList<PersistableBundle>(); // empty list
}
/**
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c8e1780..07aa800 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -22,6 +22,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.ProxyInfo;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.os.RemoteCallback;
import android.os.UserHandle;
import java.util.List;
@@ -183,8 +184,10 @@ interface IDevicePolicyManager {
boolean getCrossProfileCallerIdDisabled(in ComponentName who);
boolean getCrossProfileCallerIdDisabledForUser(int userId);
- void setTrustAgentFeaturesEnabled(in ComponentName admin, in ComponentName agent, in List<String> features, int userId);
- List<String> getTrustAgentFeaturesEnabled(in ComponentName admin, in ComponentName agent, int userId);
+ void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent,
+ in PersistableBundle args, int userId);
+ List<PersistableBundle> getTrustAgentConfiguration(in ComponentName admin,
+ in ComponentName agent, int userId);
boolean addCrossProfileWidgetProvider(in ComponentName admin, String packageName);
boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName);
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 2853c58..c8f9b7d 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -515,7 +515,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
// last chance, check against any uri grants
- if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ final int callingUserId = UserHandle.getUserId(uid);
+ final Uri userUri = (mSingleUser && !UserHandle.isSameUser(mMyUid, uid))
+ ? maybeAddUserId(uri, callingUserId) : uri;
+ if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
== PERMISSION_GRANTED) {
return;
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 7676e4b..e06f034 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -41,6 +41,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
import android.os.StrictMode;
import android.os.UserHandle;
import android.provider.DocumentsContract;
@@ -7498,8 +7499,10 @@ public class Intent implements Parcelable, Cloneable {
*/
public void prepareToEnterProcess() {
if (mContentUserHint != UserHandle.USER_CURRENT) {
- fixUris(mContentUserHint);
- mContentUserHint = UserHandle.USER_CURRENT;
+ if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) {
+ fixUris(mContentUserHint);
+ mContentUserHint = UserHandle.USER_CURRENT;
+ }
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiRecordListener.java b/core/java/android/hardware/hdmi/HdmiRecordListener.java
index 29f6cfc..90b7768 100644
--- a/core/java/android/hardware/hdmi/HdmiRecordListener.java
+++ b/core/java/android/hardware/hdmi/HdmiRecordListener.java
@@ -39,6 +39,8 @@ public abstract class HdmiRecordListener {
/**
* Called when one touch record is started or failed during initialization.
*
+ * @param recorderAddress An address of recorder that reports result of one touch record
+ * request
* @param result result code. For more details, please look at all constants starting with
* "ONE_TOUCH_RECORD_". Only
* {@link HdmiControlManager#ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE},
@@ -47,15 +49,17 @@ public abstract class HdmiRecordListener {
* {@link HdmiControlManager#ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT} mean normal
* start of recording; otherwise, describes failure.
*/
- public void onOneTouchRecordResult(int result) {
+ public void onOneTouchRecordResult(int recorderAddress, int result) {
}
/**
* Called when timer recording is started or failed during initialization.
*
+ * @param recorderAddress An address of recorder that reports result of timer recording
+ * request
* @param data timer status data. For more details, look at {@link TimerStatusData}.
*/
- public void onTimerRecordingResult(TimerStatusData data) {
+ public void onTimerRecordingResult(int recorderAddress, TimerStatusData data) {
}
/**
@@ -230,6 +234,8 @@ public abstract class HdmiRecordListener {
/**
* Called when receiving result for clear timer recording request.
*
+ * @param recorderAddress An address of recorder that reports result of clear timer recording
+ * request
* @param result result of clear timer. It should be one of
* {@link HdmiControlManager#CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_RECORDING}
* {@link HdmiControlManager#CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_MATCHING},
@@ -239,6 +245,6 @@ public abstract class HdmiRecordListener {
* {@link HdmiControlManager#CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE},
* {@link HdmiControlManager#CLEAR_TIMER_STATUS_CEC_DISABLE}.
*/
- public void onClearTimerRecordingResult(int result) {
+ public void onClearTimerRecordingResult(int recorderAddress, int result) {
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index dbfb4ef..cef17dd 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -226,19 +226,19 @@ public final class HdmiTvClient extends HdmiClient {
}
@Override
- public void onOneTouchRecordResult(int result) {
- callback.onOneTouchRecordResult(result);
+ public void onOneTouchRecordResult(int recorderAddress, int result) {
+ callback.onOneTouchRecordResult(recorderAddress, result);
}
@Override
- public void onTimerRecordingResult(int result) {
- callback.onTimerRecordingResult(
+ public void onTimerRecordingResult(int recorderAddress, int result) {
+ callback.onTimerRecordingResult(recorderAddress,
HdmiRecordListener.TimerStatusData.parseFrom(result));
}
@Override
- public void onClearTimerRecordingResult(int result) {
- callback.onClearTimerRecordingResult(result);
+ public void onClearTimerRecordingResult(int recorderAddress, int result) {
+ callback.onClearTimerRecordingResult(recorderAddress, result);
}
};
}
diff --git a/core/java/android/hardware/hdmi/IHdmiRecordListener.aidl b/core/java/android/hardware/hdmi/IHdmiRecordListener.aidl
index 44d9065..d2deb38 100644
--- a/core/java/android/hardware/hdmi/IHdmiRecordListener.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiRecordListener.aidl
@@ -31,19 +31,25 @@ package android.hardware.hdmi;
/**
* Called when one touch record is started or failed during initialization.
*
+ * @param recorderAddress An address of recorder that reports result of one touch record
+ * request
* @param result result code for one touch record
*/
- void onOneTouchRecordResult(int result);
+ void onOneTouchRecordResult(int recorderAddress, int result);
/**
* Called when timer recording is started or failed during initialization.
-
+ *
+ * @param recorderAddress An address of recorder that reports result of timer recording
+ * request
* @param result result code for timer recording
*/
- void onTimerRecordingResult(int result);
+ void onTimerRecordingResult(int recorderAddress, int result);
/**
* Called when receiving result for clear timer recording request.
*
- * @param result result of clear timer.
+ * @param recorderAddress An address of recorder that reports result of clear timer recording
+ * request
+ * @param result result of clear timer
*/
- void onClearTimerRecordingResult(int result);
+ void onClearTimerRecordingResult(int recorderAddress, int result);
} \ No newline at end of file
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 9194ca8..1c9f4c6 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1012,60 +1012,57 @@ public class ConnectivityManager {
return null;
}
+ /**
+ * Guess what the network request was trying to say so that the resulting
+ * network is accessible via the legacy (deprecated) API such as
+ * requestRouteToHost.
+ * This means we should try to be fairly preceise about transport and
+ * capability but ignore things such as networkSpecifier.
+ * If the request has more than one transport or capability it doesn't
+ * match the old legacy requests (they selected only single transport/capability)
+ * so this function cannot map the request to a single legacy type and
+ * the resulting network will not be available to the legacy APIs.
+ *
+ * TODO - This should be removed when the legacy APIs are removed.
+ */
private int inferLegacyTypeForNetworkCapabilities(NetworkCapabilities netCap) {
if (netCap == null) {
return TYPE_NONE;
}
+
if (!netCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return TYPE_NONE;
}
+
+ String type = null;
+ int result = TYPE_NONE;
+
if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
- if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableCBS"))) {
- return TYPE_MOBILE_CBS;
- } else {
- return TYPE_NONE;
- }
- }
- if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
- if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableIMS"))) {
- return TYPE_MOBILE_IMS;
- } else {
- return TYPE_NONE;
- }
- }
- if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
- if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableFOTA"))) {
- return TYPE_MOBILE_FOTA;
- } else {
- return TYPE_NONE;
- }
- }
- if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
- if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableDUN"))) {
- return TYPE_MOBILE_DUN;
- } else {
- return TYPE_NONE;
- }
- }
- if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
- if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableSUPL"))) {
- return TYPE_MOBILE_SUPL;
- } else {
- return TYPE_NONE;
- }
- }
- if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
- if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableMMS"))) {
- return TYPE_MOBILE_MMS;
- } else {
- return TYPE_NONE;
- }
- }
- if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
- if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableHIPRI"))) {
- return TYPE_MOBILE_HIPRI;
- } else {
- return TYPE_NONE;
+ type = "enableCBS";
+ result = TYPE_MOBILE_CBS;
+ } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
+ type = "enableIMS";
+ result = TYPE_MOBILE_IMS;
+ } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
+ type = "enableFOTA";
+ result = TYPE_MOBILE_FOTA;
+ } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
+ type = "enableDUN";
+ result = TYPE_MOBILE_DUN;
+ } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
+ type = "enableSUPL";
+ result = TYPE_MOBILE_SUPL;
+ } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ type = "enableMMS";
+ result = TYPE_MOBILE_MMS;
+ } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+ type = "enableHIPRI";
+ result = TYPE_MOBILE_HIPRI;
+ }
+ if (type != null) {
+ NetworkCapabilities testCap = networkCapabilitiesForFeature(TYPE_MOBILE, type);
+ if (testCap.equalsNetCapabilities(netCap) && testCap.equalsTransportTypes(netCap)) {
+ return result;
}
}
return TYPE_NONE;
@@ -2381,17 +2378,15 @@ public class ConnectivityManager {
/**
* The lookup key for a {@link Network} object included with the intent after
- * succesfully finding a network for the applications request. Retrieve it with
+ * successfully finding a network for the applications request. Retrieve it with
* {@link android.content.Intent#getParcelableExtra(String)}.
- * @hide
*/
public static final String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
/**
* The lookup key for a {@link NetworkRequest} object included with the intent after
- * succesfully finding a network for the applications request. Retrieve it with
+ * successfully finding a network for the applications request. Retrieve it with
* {@link android.content.Intent#getParcelableExtra(String)}.
- * @hide
*/
public static final String EXTRA_NETWORK_REQUEST_NETWORK_REQUEST =
"networkRequestNetworkRequest";
@@ -2400,7 +2395,7 @@ public class ConnectivityManager {
/**
* Request a network to satisfy a set of {@link NetworkCapabilities}.
*
- * This function behavies identically to the version that takes a NetworkCallback, but instead
+ * This function behaves identically to the version that takes a NetworkCallback, but instead
* of {@link NetworkCallback} a {@link PendingIntent} is used. This means
* the request may outlive the calling application and get called back when a suitable
* network is found.
@@ -2421,21 +2416,46 @@ public class ConnectivityManager {
* two Intents defined by {@link Intent#filterEquals}), then it will be removed and
* replaced by this one, effectively releasing the previous {@link NetworkRequest}.
* <p>
- * The request may be released normally by calling {@link #unregisterNetworkCallback}.
+ * The request may be released normally by calling
+ * {@link #releaseNetworkRequest(android.app.PendingIntent)}.
*
* @param request {@link NetworkRequest} describing this request.
* @param operation Action to perform when the network is available (corresponds
* to the {@link NetworkCallback#onAvailable} call. Typically
- * comes from {@link PendingIntent#getBroadcast}.
- * @hide
+ * comes from {@link PendingIntent#getBroadcast}. Cannot be null.
*/
public void requestNetwork(NetworkRequest request, PendingIntent operation) {
+ checkPendingIntent(operation);
try {
mService.pendingRequestForNetwork(request.networkCapabilities, operation);
} catch (RemoteException e) {}
}
/**
+ * Removes a request made via {@link #requestNetwork(NetworkRequest, android.app.PendingIntent)}
+ * <p>
+ * This method has the same behavior as {@link #unregisterNetworkCallback} with respect to
+ * releasing network resources and disconnecting.
+ *
+ * @param operation A PendingIntent equal (as defined by {@link Intent#filterEquals}) to the
+ * PendingIntent passed to
+ * {@link #requestNetwork(NetworkRequest, android.app.PendingIntent)} with the
+ * corresponding NetworkRequest you'd like to remove. Cannot be null.
+ */
+ public void releaseNetworkRequest(PendingIntent operation) {
+ checkPendingIntent(operation);
+ try {
+ mService.releasePendingNetworkRequest(operation);
+ } catch (RemoteException e) {}
+ }
+
+ private void checkPendingIntent(PendingIntent intent) {
+ if (intent == null) {
+ throw new IllegalArgumentException("PendingIntent cannot be null.");
+ }
+ }
+
+ /**
* Registers to receive notifications about all networks which satisfy the given
* {@link NetworkRequest}. The callbacks will continue to be called until
* either the application exits or {@link #unregisterNetworkCallback} is called
@@ -2451,7 +2471,7 @@ public class ConnectivityManager {
/**
* Unregisters callbacks about and possibly releases networks originating from
* {@link #requestNetwork} and {@link #registerNetworkCallback} calls. If the
- * given {@code NetworkCallback} had previosuly been used with {@code #requestNetwork},
+ * given {@code NetworkCallback} had previously been used with {@code #requestNetwork},
* any networks that had been connected to only to satisfy that request will be
* disconnected.
*
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 71df60a..6159e1e 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -200,7 +200,7 @@ public class DhcpResults extends StaticIpConfiguration {
vendorInfo = info;
}
- public void setDomains(String domains) {
- domains = domains;
+ public void setDomains(String newDomains) {
+ domains = newDomains;
}
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index a983d88..a7bbc53 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -156,6 +156,8 @@ interface IConnectivityManager
NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities,
in PendingIntent operation);
+ void releasePendingNetworkRequest(in PendingIntent operation);
+
NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities,
in Messenger messenger, in IBinder binder);
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 1efe478..ce7ad65 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -235,7 +235,8 @@ public final class NetworkCapabilities implements Parcelable {
return ((nc.mNetworkCapabilities & this.mNetworkCapabilities) == this.mNetworkCapabilities);
}
- private boolean equalsNetCapabilities(NetworkCapabilities nc) {
+ /** @hide */
+ public boolean equalsNetCapabilities(NetworkCapabilities nc) {
return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
}
@@ -344,7 +345,8 @@ public final class NetworkCapabilities implements Parcelable {
return ((this.mTransportTypes == 0) ||
((this.mTransportTypes & nc.mTransportTypes) != 0));
}
- private boolean equalsTransportTypes(NetworkCapabilities nc) {
+ /** @hide */
+ public boolean equalsTransportTypes(NetworkCapabilities nc) {
return (nc.mTransportTypes == this.mTransportTypes);
}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 3f68a44..a939cce 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -41,10 +41,10 @@ import android.os.UserHandle;
* <ul>
* <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
* <li>Includes a receiver for {@link #ACTION_SCORE_NETWORKS} guarded by the
- * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission which scores networks
- * and (eventually) calls {@link #updateScores} with the results. If this receiver specifies an
- * android:label attribute, this label will be used when referring to the application throughout
- * system settings; otherwise, the application label will be used.
+ * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission which scores
+ * networks and (eventually) calls {@link #updateScores} with the results. If this receiver
+ * specifies an android:label attribute, this label will be used when referring to the
+ * application throughout system settings; otherwise, the application label will be used.
* </ul>
*
* <p>The system keeps track of an active scorer application; at any time, only this application
@@ -192,12 +192,15 @@ public class NetworkScoreManager {
/**
* Set the active scorer to a new package and clear existing scores.
*
+ * <p>Should never be called directly without obtaining user consent. This can be done by using
+ * the {@link #ACTION_CHANGE_ACTIVE} broadcast, or using a custom configuration activity.
+ *
* @return true if the operation succeeded, or false if the new package is not a valid scorer.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission indicating
- * that it can manage scorer applications.
+ * {@link android.Manifest.permission#SCORE_NETWORKS} permission.
* @hide
*/
+ @SystemApi
public boolean setActiveScorer(String packageName) throws SecurityException {
try {
return mService.setActiveScorer(packageName);
@@ -228,7 +231,7 @@ public class NetworkScoreManager {
*
* @return true if the broadcast was sent, or false if there is no active scorer.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+ * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
* @hide
*/
public boolean requestScores(NetworkKey[] networks) throws SecurityException {
@@ -252,7 +255,7 @@ public class NetworkScoreManager {
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+ * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @hide
*/
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index c33f5ec..46f7194 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -79,7 +79,7 @@ public final class NetworkScorerAppManager {
* <ul>
* <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
* <li>Includes a receiver for {@link NetworkScoreManager#ACTION_SCORE_NETWORKS} guarded by the
- * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+ * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
* </ul>
*
* @return the list of scorers, or the empty list if there are no valid scorers.
@@ -98,8 +98,8 @@ public final class NetworkScorerAppManager {
// Should never happen with queryBroadcastReceivers, but invalid nonetheless.
continue;
}
- if (!permission.BROADCAST_SCORE_NETWORKS.equals(receiverInfo.permission)) {
- // Receiver doesn't require the BROADCAST_SCORE_NETWORKS permission, which means
+ if (!permission.BROADCAST_NETWORK_PRIVILEGED.equals(receiverInfo.permission)) {
+ // Receiver doesn't require the BROADCAST_NETWORK_PRIVILEGED permission, which means
// anyone could trigger network scoring and flood the framework with score requests.
continue;
}
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 5a273cf..598a503 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -107,6 +107,7 @@ public class StaticIpConfiguration implements Parcelable {
for (InetAddress dns : dnsServers) {
lp.addDnsServer(dns);
}
+ lp.setDomains(domains);
return lp;
}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 084ca30..3f42d25 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -165,7 +165,7 @@ public final class Debug
public int otherSwappedOut;
/** @hide */
- public static final int NUM_OTHER_STATS = 16;
+ public static final int NUM_OTHER_STATS = 17;
/** @hide */
public static final int NUM_DVK_STATS = 5;
@@ -296,23 +296,24 @@ public final class Debug
case 1: return "Stack";
case 2: return "Cursor";
case 3: return "Ashmem";
- case 4: return "Other dev";
- case 5: return ".so mmap";
- case 6: return ".jar mmap";
- case 7: return ".apk mmap";
- case 8: return ".ttf mmap";
- case 9: return ".dex mmap";
- case 10: return "code mmap";
- case 11: return "image mmap";
- case 12: return "Other mmap";
- case 13: return "Graphics";
- case 14: return "GL";
- case 15: return "Memtrack";
- case 16: return ".Heap";
- case 17: return ".LOS";
- case 18: return ".LinearAlloc";
- case 19: return ".GC";
- case 20: return ".JITCache";
+ case 4: return "Gfx driver";
+ case 5: return "Other dev";
+ case 6: return ".so mmap";
+ case 7: return ".jar mmap";
+ case 8: return ".apk mmap";
+ case 9: return ".ttf mmap";
+ case 10: return ".dex mmap";
+ case 11: return ".oat mmap";
+ case 12: return ".art mmap";
+ case 13: return "Other mmap";
+ case 14: return "Graphics";
+ case 15: return "GL";
+ case 16: return "Memtrack";
+ case 17: return ".Heap";
+ case 18: return ".LOS";
+ case 19: return ".LinearAlloc";
+ case 20: return ".GC";
+ case 21: return ".JITCache";
default: return "????";
}
}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 9a84a1e..36401eb 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -78,6 +78,7 @@ public class ZenModeConfig implements Parcelable {
private static final String ALLOW_ATT_EVENTS = "events";
private static final String SLEEP_TAG = "sleep";
private static final String SLEEP_ATT_MODE = "mode";
+ private static final String SLEEP_ATT_NONE = "none";
private static final String SLEEP_ATT_START_HR = "startHour";
private static final String SLEEP_ATT_START_MIN = "startMin";
@@ -107,6 +108,7 @@ public class ZenModeConfig implements Parcelable {
public int sleepStartMinute; // 0-59
public int sleepEndHour;
public int sleepEndMinute;
+ public boolean sleepNone; // false = priority, true = none
public ComponentName[] conditionComponents;
public Uri[] conditionIds;
public Condition exitCondition;
@@ -125,6 +127,7 @@ public class ZenModeConfig implements Parcelable {
sleepStartMinute = source.readInt();
sleepEndHour = source.readInt();
sleepEndMinute = source.readInt();
+ sleepNone = source.readInt() == 1;
int len = source.readInt();
if (len > 0) {
conditionComponents = new ComponentName[len];
@@ -155,6 +158,7 @@ public class ZenModeConfig implements Parcelable {
dest.writeInt(sleepStartMinute);
dest.writeInt(sleepEndHour);
dest.writeInt(sleepEndMinute);
+ dest.writeInt(sleepNone ? 1 : 0);
if (conditionComponents != null && conditionComponents.length > 0) {
dest.writeInt(conditionComponents.length);
dest.writeTypedArray(conditionComponents, 0);
@@ -182,6 +186,7 @@ public class ZenModeConfig implements Parcelable {
.append(",sleepMode=").append(sleepMode)
.append(",sleepStart=").append(sleepStartHour).append('.').append(sleepStartMinute)
.append(",sleepEnd=").append(sleepEndHour).append('.').append(sleepEndMinute)
+ .append(",sleepNone=").append(sleepNone)
.append(",conditionComponents=")
.append(conditionComponents == null ? null : TextUtils.join(",", conditionComponents))
.append(",conditionIds=")
@@ -214,6 +219,7 @@ public class ZenModeConfig implements Parcelable {
&& other.allowFrom == allowFrom
&& other.allowEvents == allowEvents
&& Objects.equals(other.sleepMode, sleepMode)
+ && other.sleepNone == sleepNone
&& other.sleepStartHour == sleepStartHour
&& other.sleepStartMinute == sleepStartMinute
&& other.sleepEndHour == sleepEndHour
@@ -226,7 +232,7 @@ public class ZenModeConfig implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(allowCalls, allowMessages, allowFrom, allowEvents, sleepMode,
+ return Objects.hash(allowCalls, allowMessages, allowFrom, allowEvents, sleepMode, sleepNone,
sleepStartHour, sleepStartMinute, sleepEndHour, sleepEndMinute,
Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds),
exitCondition, exitConditionComponent);
@@ -302,6 +308,7 @@ public class ZenModeConfig implements Parcelable {
} else if (SLEEP_TAG.equals(tag)) {
final String mode = parser.getAttributeValue(null, SLEEP_ATT_MODE);
rt.sleepMode = isValidSleepMode(mode)? mode : null;
+ rt.sleepNone = safeBoolean(parser, SLEEP_ATT_NONE, false);
final int startHour = safeInt(parser, SLEEP_ATT_START_HR, 0);
final int startMinute = safeInt(parser, SLEEP_ATT_START_MIN, 0);
final int endHour = safeInt(parser, SLEEP_ATT_END_HR, 0);
@@ -345,6 +352,7 @@ public class ZenModeConfig implements Parcelable {
if (sleepMode != null) {
out.attribute(null, SLEEP_ATT_MODE, sleepMode);
}
+ out.attribute(null, SLEEP_ATT_NONE, Boolean.toString(sleepNone));
out.attribute(null, SLEEP_ATT_START_HR, Integer.toString(sleepStartHour));
out.attribute(null, SLEEP_ATT_START_MIN, Integer.toString(sleepStartMinute));
out.attribute(null, SLEEP_ATT_END_HR, Integer.toString(sleepEndHour));
@@ -498,7 +506,7 @@ public class ZenModeConfig implements Parcelable {
}
// For built-in conditions
- private static final String SYSTEM_AUTHORITY = "android";
+ public static final String SYSTEM_AUTHORITY = "android";
// Built-in countdown conditions, e.g. condition://android/countdown/1399917958951
private static final String COUNTDOWN_PATH = "countdown";
diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl
index bd80a3f..bb0c2b2 100644
--- a/core/java/android/service/trust/ITrustAgentService.aidl
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -15,7 +15,7 @@
*/
package android.service.trust;
-import android.os.Bundle;
+import android.os.PersistableBundle;
import android.service.trust.ITrustAgentServiceCallback;
/**
@@ -25,6 +25,6 @@ import android.service.trust.ITrustAgentServiceCallback;
interface ITrustAgentService {
oneway void onUnlockAttempt(boolean successful);
oneway void onTrustTimeout();
+ oneway void onConfigure(in List<PersistableBundle> options, IBinder token);
oneway void setCallback(ITrustAgentServiceCallback callback);
- oneway void setTrustAgentFeaturesEnabled(in Bundle options, IBinder token);
}
diff --git a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
index b107bcc..76b2be0 100644
--- a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
+++ b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
@@ -27,5 +27,5 @@ oneway interface ITrustAgentServiceCallback {
void grantTrust(CharSequence message, long durationMs, boolean initiatedByUser);
void revokeTrust();
void setManagingTrust(boolean managingTrust);
- void onSetTrustAgentFeaturesEnabledCompleted(boolean result, IBinder token);
+ void onConfigureCompleted(boolean result, IBinder token);
}
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index 3ef5b37..00d60c0 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -29,11 +29,14 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import android.util.Slog;
+import java.util.List;
+
/**
* A service that notifies the system about whether it believes the environment of the device
* to be trusted.
@@ -86,16 +89,46 @@ public class TrustAgentService extends Service {
*/
public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
+ private static final int MSG_UNLOCK_ATTEMPT = 1;
+ private static final int MSG_CONFIGURE = 2;
+ private static final int MSG_TRUST_TIMEOUT = 3;
+
/**
- * A white list of features that the given trust agent should support when otherwise disabled
- * by device policy.
- * @hide
+ * Container class for a list of configuration options and helper methods
*/
- public static final String KEY_FEATURES = "trust_agent_features";
+ public static final class Configuration {
+ public final List<PersistableBundle> options;
+ public Configuration(List<PersistableBundle> opts) {
+ options = opts;
+ }
- private static final int MSG_UNLOCK_ATTEMPT = 1;
- private static final int MSG_SET_TRUST_AGENT_FEATURES_ENABLED = 2;
- private static final int MSG_TRUST_TIMEOUT = 3;
+ /**
+ * Very basic method to determine if all bundles have the given feature, regardless
+ * of type.
+ * @param option String to search for.
+ * @return true if found in all bundles.
+ */
+ public boolean hasOption(String option) {
+ if (options == null || options.size() == 0) return false;
+ final int N = options.size();
+ for (int i = 0; i < N; i++) {
+ if (!options.get(i).containsKey(option)) return false;
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Class containing raw data for a given configuration request.
+ */
+ private static final class ConfigurationData {
+ final IBinder token;
+ final List<PersistableBundle> options;
+ ConfigurationData(List<PersistableBundle> opts, IBinder t) {
+ options = opts;
+ token = t;
+ }
+ }
private ITrustAgentServiceCallback mCallback;
@@ -112,13 +145,12 @@ public class TrustAgentService extends Service {
case MSG_UNLOCK_ATTEMPT:
onUnlockAttempt(msg.arg1 != 0);
break;
- case MSG_SET_TRUST_AGENT_FEATURES_ENABLED:
- Bundle features = msg.peekData();
- IBinder token = (IBinder) msg.obj;
- boolean result = onSetTrustAgentFeaturesEnabled(features);
+ case MSG_CONFIGURE:
+ ConfigurationData data = (ConfigurationData) msg.obj;
+ boolean result = onConfigure(new Configuration(data.options));
try {
synchronized (mLock) {
- mCallback.onSetTrustAgentFeaturesEnabledCompleted(result, token);
+ mCallback.onConfigureCompleted(result, data.token);
}
} catch (RemoteException e) {
onError("calling onSetTrustAgentFeaturesEnabledCompleted()");
@@ -171,23 +203,16 @@ public class TrustAgentService extends Service {
}
/**
- * Called when device policy wants to restrict features in the agent in response to
- * {@link DevicePolicyManager#setTrustAgentFeaturesEnabled(ComponentName, ComponentName, java.util.List) }.
- * Agents that support this feature should overload this method and return 'true'.
+ * Called when device policy admin wants to enable specific options for agent in response to
+ * {@link DevicePolicyManager#setKeyguardDisabledFeatures(ComponentName, int)} and
+ * {@link DevicePolicyManager#setTrustAgentConfiguration(ComponentName, ComponentName,
+ * PersistableBundle)}.
+ * <p>Agents that support configuration options should overload this method and return 'true'.
*
- * The list of options can be obtained by calling
- * options.getStringArrayList({@link #KEY_FEATURES}). Presence of a feature string in the list
- * means it should be enabled ("white-listed"). Absence of the feature means it should be
- * disabled. An empty list means all features should be disabled.
- *
- * This function is only called if {@link DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS} is
- * set.
- *
- * @param options Option feature bundle.
- * @return true if the {@link TrustAgentService} supports this feature.
- * @hide
+ * @param options bundle containing all options or null if none.
+ * @return true if the {@link TrustAgentService} supports configuration options.
*/
- public boolean onSetTrustAgentFeaturesEnabled(Bundle options) {
+ public boolean onConfigure(Configuration options) {
return false;
}
@@ -295,6 +320,12 @@ public class TrustAgentService extends Service {
}
@Override /* Binder API */
+ public void onConfigure(List<PersistableBundle> args, IBinder token) {
+ mHandler.obtainMessage(MSG_CONFIGURE, new ConfigurationData(args, token))
+ .sendToTarget();
+ }
+
+ @Override /* Binder API */
public void setCallback(ITrustAgentServiceCallback callback) {
synchronized (mLock) {
mCallback = callback;
@@ -313,13 +344,6 @@ public class TrustAgentService extends Service {
}
}
}
-
- @Override /* Binder API */
- public void setTrustAgentFeaturesEnabled(Bundle features, IBinder token) {
- Message msg = mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_ENABLED, token);
- msg.setData(features);
- msg.sendToTarget();
- }
}
}
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 9fec9a1..933bcee 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -60,27 +60,45 @@ import libcore.icu.LocaleData;
* {@code SimpleDateFormat}.
*/
public class DateFormat {
- /** @deprecated Use a literal {@code '} instead. */
+ /**
+ * @deprecated Use a literal {@code '} instead.
+ * @removed
+ */
@Deprecated
public static final char QUOTE = '\'';
- /** @deprecated Use a literal {@code 'a'} instead. */
+ /**
+ * @deprecated Use a literal {@code 'a'} instead.
+ * @removed
+ */
@Deprecated
public static final char AM_PM = 'a';
- /** @deprecated Use a literal {@code 'a'} instead; 'A' was always equivalent to 'a'. */
+ /**
+ * @deprecated Use a literal {@code 'a'} instead; 'A' was always equivalent to 'a'.
+ * @removed
+ */
@Deprecated
public static final char CAPITAL_AM_PM = 'A';
- /** @deprecated Use a literal {@code 'd'} instead. */
+ /**
+ * @deprecated Use a literal {@code 'd'} instead.
+ * @removed
+ */
@Deprecated
public static final char DATE = 'd';
- /** @deprecated Use a literal {@code 'E'} instead. */
+ /**
+ * @deprecated Use a literal {@code 'E'} instead.
+ * @removed
+ */
@Deprecated
public static final char DAY = 'E';
- /** @deprecated Use a literal {@code 'h'} instead. */
+ /**
+ * @deprecated Use a literal {@code 'h'} instead.
+ * @removed
+ */
@Deprecated
public static final char HOUR = 'h';
@@ -88,31 +106,51 @@ public class DateFormat {
* @deprecated Use a literal {@code 'H'} (for compatibility with {@link SimpleDateFormat}
* and Unicode) or {@code 'k'} (for compatibility with Android releases up to and including
* Jelly Bean MR-1) instead. Note that the two are incompatible.
+ *
+ * @removed
*/
@Deprecated
public static final char HOUR_OF_DAY = 'k';
- /** @deprecated Use a literal {@code 'm'} instead. */
+ /**
+ * @deprecated Use a literal {@code 'm'} instead.
+ * @removed
+ */
@Deprecated
public static final char MINUTE = 'm';
- /** @deprecated Use a literal {@code 'M'} instead. */
+ /**
+ * @deprecated Use a literal {@code 'M'} instead.
+ * @removed
+ */
@Deprecated
public static final char MONTH = 'M';
- /** @deprecated Use a literal {@code 'L'} instead. */
+ /**
+ * @deprecated Use a literal {@code 'L'} instead.
+ * @removed
+ */
@Deprecated
public static final char STANDALONE_MONTH = 'L';
- /** @deprecated Use a literal {@code 's'} instead. */
+ /**
+ * @deprecated Use a literal {@code 's'} instead.
+ * @removed
+ */
@Deprecated
public static final char SECONDS = 's';
- /** @deprecated Use a literal {@code 'z'} instead. */
+ /**
+ * @deprecated Use a literal {@code 'z'} instead.
+ * @removed
+ */
@Deprecated
public static final char TIME_ZONE = 'z';
- /** @deprecated Use a literal {@code 'y'} instead. */
+ /**
+ * @deprecated Use a literal {@code 'y'} instead.
+ * @removed
+ */
@Deprecated
public static final char YEAR = 'y';
@@ -306,9 +344,9 @@ public class DateFormat {
}
/**
- * Gets the current date format stored as a char array. The array will contain
- * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order
- * specified by the user's format preference. Note that this order is
+ * Gets the current date format stored as a char array. Returns a 3 element
+ * array containing the day ({@code 'd'}), month ({@code 'M'}), and year ({@code 'y'}))
+ * in the order specified by the user's format preference. Note that this order is
* <i>only</i> appropriate for all-numeric dates; spelled-out (MEDIUM and LONG)
* dates will generally contain other punctuation, spaces, or words,
* not just the day, month, and year, and not necessarily in the same
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index b0cbcd2..b467f5a 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -110,6 +110,7 @@ public final class Formatter {
private static final int SECONDS_PER_MINUTE = 60;
private static final int SECONDS_PER_HOUR = 60 * 60;
private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+ private static final int MILLIS_PER_MINUTE = 1000 * 60;
/**
* Returns elapsed time for the given millis, in the following format:
@@ -171,4 +172,24 @@ public final class Formatter {
return context.getString(com.android.internal.R.string.durationSeconds, seconds);
}
}
+
+ /**
+ * Returns elapsed time for the given millis, in the following format:
+ * 1 day 5 hrs; will include at most two units, can go down to minutes precision.
+ * @param context the application context
+ * @param millis the elapsed time in milli seconds
+ * @return the formatted elapsed time
+ * @hide
+ */
+ public static String formatShortElapsedTimeRoundingUpToMinutes(Context context, long millis) {
+ long minutesRoundedUp = (millis + MILLIS_PER_MINUTE - 1) / MILLIS_PER_MINUTE;
+
+ if (minutesRoundedUp == 0) {
+ return context.getString(com.android.internal.R.string.durationMinutes, 0);
+ } else if (minutesRoundedUp == 1) {
+ return context.getString(com.android.internal.R.string.durationMinute, 1);
+ }
+
+ return formatShortElapsedTime(context, minutesRoundedUp * MILLIS_PER_MINUTE);
+ }
}
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index e99c2cf..2705bcf 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -84,8 +84,8 @@ import com.android.internal.R;
*
* <p>Custom transition classes may be instantiated with a <code>transition</code> tag:</p>
* <pre>&lt;transition class="my.app.transition.CustomTransition"/></pre>
- * <p>Custom transition classes loaded from XML must have a public nullary (no argument)
- * constructor.</p>
+ * <p>Custom transition classes loaded from XML should have a public constructor taking
+ * a {@link android.content.Context} and {@link android.util.AttributeSet}.</p>
*
* <p>Note that attributes for the transition are not required, just as they are
* optional when declared in code; Transitions created from XML resources will use
@@ -955,7 +955,7 @@ public abstract class Transition implements Cloneable {
* Views with different IDs, or no IDs whatsoever, will be ignored.
*
* <p>Note that using ids to specify targets implies that ids should be unique
- * within the view hierarchy underneat the scene root.</p>
+ * within the view hierarchy underneath the scene root.</p>
*
* @see View#getId()
* @param targetId The id of a target view, must be a positive number.
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 1cadf69..5e05683 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -1109,15 +1109,17 @@ final class AccessibilityInteractionController {
|| accessibilityViewId == providerHost.getAccessibilityViewId()) {
final AccessibilityNodeInfo parent;
if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- parent = provider.createAccessibilityNodeInfo(
- virtualDescendantId);
+ parent = provider.createAccessibilityNodeInfo(virtualDescendantId);
} else {
- parent= provider.createAccessibilityNodeInfo(
+ parent = provider.createAccessibilityNodeInfo(
AccessibilityNodeProvider.HOST_VIEW_ID);
}
- if (parent != null) {
- outInfos.add(parent);
+ if (parent == null) {
+ // Couldn't obtain the parent, which means we have a
+ // disconnected sub-tree. Abort prefetch immediately.
+ return;
}
+ outInfos.add(parent);
parentNodeId = parent.getParentNodeId();
accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
parentNodeId);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 562d138..90fdbe2 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -319,6 +319,7 @@ public class Surface implements Parcelable {
* @return A canvas for drawing into the surface.
*
* @throws IllegalStateException If the canvas cannot be locked.
+ * @hide
*/
public Canvas lockHardwareCanvas() {
synchronized (mLock) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6450146..ea0a077 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -728,8 +728,8 @@ public final class ViewRootImpl implements ViewParent,
}
final Rect insets = attrs.surfaceInsets;
- final boolean hasSurfaceInsets = insets.left == 0 || insets.right == 0
- || insets.top == 0 || insets.bottom == 0;
+ final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
+ || insets.top != 0 || insets.bottom != 0;
final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
mAttachInfo.mHardwareRenderer = HardwareRenderer.create(mContext, translucent);
if (mAttachInfo.mHardwareRenderer != null) {
@@ -1746,8 +1746,8 @@ public final class ViewRootImpl implements ViewParent,
if (hwInitialized ||
mWidth != mAttachInfo.mHardwareRenderer.getWidth() ||
mHeight != mAttachInfo.mHardwareRenderer.getHeight()) {
- final Rect surfaceInsets = params != null ? params.surfaceInsets : null;
- mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight, surfaceInsets);
+ mAttachInfo.mHardwareRenderer.setup(
+ mWidth, mHeight, mWindowAttributes.surfaceInsets);
if (!hwInitialized) {
mAttachInfo.mHardwareRenderer.invalidate(mSurface);
mFullRedrawNeeded = true;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 5926d5f..82b1073 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -118,6 +118,9 @@ public final class WindowManagerGlobal {
private Runnable mSystemPropertyUpdater;
+ /** Default token to apply to added views. */
+ private IBinder mDefaultToken;
+
private WindowManagerGlobal() {
}
@@ -169,6 +172,17 @@ public final class WindowManagerGlobal {
}
}
+ /**
+ * Sets the default token to use in {@link #addView} when no parent window
+ * token is available and no token has been explicitly set in the view's
+ * layout params.
+ *
+ * @param token Default window token to apply to added views.
+ */
+ public void setDefaultToken(IBinder token) {
+ mDefaultToken = token;
+ }
+
public String[] getViewRootNames() {
synchronized (mLock) {
final int numRoots = mRoots.size();
@@ -216,6 +230,10 @@ public final class WindowManagerGlobal {
}
}
+ if (wparams.token == null && mDefaultToken != null) {
+ wparams.token = mDefaultToken;
+ }
+
ViewRootImpl root;
View panelParentView = null;
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index fcf66f6..f9544d0 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -107,9 +107,9 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
mAdapter.setRange(mMinDate, mMaxDate);
- if (constrainCalendar(mSelectedDay, mMinDate, mMaxDate)) {
- goTo(mSelectedDay, false, true, true);
- }
+ // Changing the min/max date changes the selection position since we
+ // don't really have stable IDs.
+ goTo(mSelectedDay, false, true, true);
}
/**
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index d4d186c..f90d64a 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -1752,6 +1752,17 @@ public class Toolbar extends ViewGroup {
}
/**
+ * Accessor to enable LayoutLib to get ActionMenuPresenter directly.
+ */
+ ActionMenuPresenter getOuterActionMenuPresenter() {
+ return mOuterActionMenuPresenter;
+ }
+
+ Context getPopupContext() {
+ return mPopupContext;
+ }
+
+ /**
* Interface responsible for receiving menu item click events if the items themselves
* do not have individual item click listeners.
*/
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 0bc1a8d..64bd6b6 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -20,6 +20,7 @@ import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
@@ -75,16 +76,21 @@ public class ChooserActivity extends ResolverActivity {
}
@Override
- public Intent getReplacementIntent(String packageName, Intent defIntent) {
+ public Intent getReplacementIntent(ActivityInfo aInfo, Intent defIntent) {
+ Intent result = defIntent;
if (mReplacementExtras != null) {
- final Bundle replExtras = mReplacementExtras.getBundle(packageName);
+ final Bundle replExtras = mReplacementExtras.getBundle(aInfo.packageName);
if (replExtras != null) {
- final Intent result = new Intent(defIntent);
+ result = new Intent(defIntent);
result.putExtras(replExtras);
- return result;
}
}
- return defIntent;
+ if (aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER)
+ || aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+ result = Intent.createChooser(result,
+ getIntent().getCharSequenceExtra(Intent.EXTRA_TITLE));
+ }
+ return result;
}
@Override
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 6e2f84a..9656a21 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -58,21 +58,22 @@ public class IntentForwarderActivity extends Activity {
Intent intentReceived = getIntent();
String className = intentReceived.getComponent().getClassName();
- final UserHandle userDest;
+ final int targetUserId;
final int userMessageId;
if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) {
userMessageId = com.android.internal.R.string.forward_intent_to_owner;
- userDest = UserHandle.OWNER;
+ targetUserId = UserHandle.USER_OWNER;
} else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
userMessageId = com.android.internal.R.string.forward_intent_to_work;
- userDest = getManagedProfile();
+ targetUserId = getManagedProfile();
} else {
Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly");
userMessageId = -1;
- userDest = null;
+ targetUserId = UserHandle.USER_NULL;
}
- if (userDest == null) { // This covers the case where there is no managed profile.
+ if (targetUserId == UserHandle.USER_NULL) {
+ // This covers the case where there is no managed profile.
finish();
return;
}
@@ -83,31 +84,24 @@ public class IntentForwarderActivity extends Activity {
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
|Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
int callingUserId = getUserId();
- IPackageManager ipm = AppGlobals.getPackageManager();
- String resolvedType = newIntent.resolveTypeIfNeeded(getContentResolver());
- boolean canForward = false;
- Intent selector = newIntent.getSelector();
- if (selector == null) {
- selector = newIntent;
- }
- try {
- canForward = ipm.canForwardTo(selector, resolvedType, callingUserId,
- userDest.getIdentifier());
- } catch (RemoteException e) {
- Slog.e(TAG, "PackageManagerService is dead?");
- }
- if (canForward) {
- newIntent.setContentUserHint(callingUserId);
+
+ if (canForward(newIntent, targetUserId)) {
+ if (newIntent.getAction().equals(Intent.ACTION_CHOOSER)) {
+ Intent innerIntent = (Intent) newIntent.getParcelableExtra(Intent.EXTRA_INTENT);
+ innerIntent.setContentUserHint(callingUserId);
+ } else {
+ newIntent.setContentUserHint(callingUserId);
+ }
final android.content.pm.ResolveInfo ri = getPackageManager().resolveActivityAsUser(
- newIntent, MATCH_DEFAULT_ONLY, userDest.getIdentifier());
+ newIntent, MATCH_DEFAULT_ONLY, targetUserId);
// Only show a disclosure if this is a normal (non-OS) app
final boolean shouldShowDisclosure =
!UserHandle.isSameApp(ri.activityInfo.applicationInfo.uid, Process.SYSTEM_UID);
try {
- startActivityAsCaller(newIntent, null, userDest.getIdentifier());
+ startActivityAsCaller(newIntent, null, targetUserId);
} catch (RuntimeException e) {
int launchedFromUid = -1;
String launchedFromPackage = "?";
@@ -129,26 +123,55 @@ public class IntentForwarderActivity extends Activity {
}
} else {
Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user "
- + callingUserId + " to user " + userDest.getIdentifier());
+ + callingUserId + " to user " + targetUserId);
}
finish();
}
+ boolean canForward(Intent intent, int targetUserId) {
+ IPackageManager ipm = AppGlobals.getPackageManager();
+ if (intent.getAction().equals(Intent.ACTION_CHOOSER)) {
+ // The EXTRA_INITIAL_INTENTS may not be allowed to be forwarded.
+ if (intent.hasExtra(Intent.EXTRA_INITIAL_INTENTS)) {
+ Slog.wtf(TAG, "An chooser intent with extra initial intents cannot be forwarded to"
+ + " a different user");
+ return false;
+ }
+ if (intent.hasExtra(Intent.EXTRA_REPLACEMENT_EXTRAS)) {
+ Slog.wtf(TAG, "A chooser intent with replacement extras cannot be forwarded to a"
+ + " different user");
+ return false;
+ }
+ intent = (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT);
+ }
+ String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+ if (intent.getSelector() != null) {
+ intent = intent.getSelector();
+ }
+ try {
+ return ipm.canForwardTo(intent, resolvedType, getUserId(),
+ targetUserId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "PackageManagerService is dead?");
+ return false;
+ }
+ }
+
/**
- * Returns the managed profile for this device or null if there is no managed
- * profile.
+ * Returns the userId of the managed profile for this device or UserHandle.USER_NULL if there is
+ * no managed profile.
*
* TODO: Remove the assumption that there is only one managed profile
* on the device.
*/
- private UserHandle getManagedProfile() {
+ private int getManagedProfile() {
UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER);
for (UserInfo userInfo : relatedUsers) {
- if (userInfo.isManagedProfile()) return new UserHandle(userInfo.id);
+ if (userInfo.isManagedProfile()) return userInfo.id;
}
Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE
+ " has been called, but there is no managed profile");
- return null;
+ return UserHandle.USER_NULL;
}
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7df76e5..376db6e 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -100,6 +100,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
private int mMaxColumns;
private int mLastSelected = ListView.INVALID_POSITION;
private boolean mResolvingHome = false;
+ private int mProfileSwitchMessageId = -1;
private UsageStatsManager mUsm;
private Map<String, UsageStats> mStats;
@@ -200,6 +201,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
List<ResolveInfo> rList, boolean alwaysUseOption) {
setTheme(R.style.Theme_DeviceDefault_Resolver);
super.onCreate(savedInstanceState);
+
+ // Determine whether we should show that intent is forwarded
+ // from managed profile to owner or other way around.
+ setProfileSwitchMessageId(intent.getContentUserHint());
+
try {
mLaunchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid(
getActivityToken());
@@ -320,6 +326,22 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
}
+ private void setProfileSwitchMessageId(int contentUserHint) {
+ if (contentUserHint != UserHandle.USER_CURRENT &&
+ contentUserHint != UserHandle.myUserId()) {
+ UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+ UserInfo originUserInfo = userManager.getUserInfo(contentUserHint);
+ boolean originIsManaged = originUserInfo != null ? originUserInfo.isManagedProfile()
+ : false;
+ boolean targetIsManaged = userManager.isManagedProfile();
+ if (originIsManaged && !targetIsManaged) {
+ mProfileSwitchMessageId = com.android.internal.R.string.forward_intent_to_owner;
+ } else if (!originIsManaged && targetIsManaged) {
+ mProfileSwitchMessageId = com.android.internal.R.string.forward_intent_to_work;
+ }
+ }
+ }
+
/**
* Turn on launch mode that is safe to use when forwarding intents received from
* applications and running in system processes. This mode uses Activity.startActivityAsCaller
@@ -529,7 +551,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
/**
* Replace me in subclasses!
*/
- public Intent getReplacementIntent(String packageName, Intent defIntent) {
+ public Intent getReplacementIntent(ActivityInfo aInfo, Intent defIntent) {
return defIntent;
}
@@ -642,6 +664,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
public void safelyStartActivity(Intent intent) {
+ // If needed, show that intent is forwarded
+ // from managed profile to owner or other way around.
+ if (mProfileSwitchMessageId != -1) {
+ Toast.makeText(this, getString(mProfileSwitchMessageId), Toast.LENGTH_LONG).show();
+ }
if (!mSafeForwardingMode) {
startActivity(intent);
onActivityStarted(intent);
@@ -943,7 +970,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
DisplayResolveInfo dri = filtered ? getItem(position) : mList.get(position);
Intent intent = new Intent(dri.origIntent != null ? dri.origIntent :
- getReplacementIntent(dri.ri.activityInfo.packageName, mIntent));
+ getReplacementIntent(dri.ri.activityInfo, mIntent));
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
|Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
ActivityInfo ai = dri.ri.activityInfo;
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 70cf9a8..d7eef6e 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -17,7 +17,7 @@
#include <jni.h>
-#include <Caches.h>
+#include <ResourceCache.h>
#if 0
#define TRACE_BITMAP(code) code
@@ -365,8 +365,8 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
#ifdef USE_OPENGL_RENDERER
- if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);
+ if (android::uirenderer::ResourceCache::hasInstance()) {
+ android::uirenderer::ResourceCache::getInstance().destructor(bitmap);
return;
}
#endif // USE_OPENGL_RENDERER
@@ -376,9 +376,9 @@ static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
#ifdef USE_OPENGL_RENDERER
- if (android::uirenderer::Caches::hasInstance()) {
+ if (android::uirenderer::ResourceCache::hasInstance()) {
bool result;
- result = android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
+ result = android::uirenderer::ResourceCache::getInstance().recycle(bitmap);
return result ? JNI_TRUE : JNI_FALSE;
}
#endif // USE_OPENGL_RENDERER
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index cf23771..be62fdd 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -21,7 +21,7 @@
#include <androidfw/ResourceTypes.h>
#include <utils/Log.h>
-#include <Caches.h>
+#include <ResourceCache.h>
#include "Paint.h"
#include "Canvas.h"
@@ -80,9 +80,9 @@ public:
static void finalize(JNIEnv* env, jobject, jlong patchHandle) {
int8_t* patch = reinterpret_cast<int8_t*>(patchHandle);
#ifdef USE_OPENGL_RENDERER
- if (android::uirenderer::Caches::hasInstance()) {
+ if (android::uirenderer::ResourceCache::hasInstance()) {
Res_png_9patch* p = (Res_png_9patch*) patch;
- android::uirenderer::Caches::getInstance().resourceCache.destructor(p);
+ android::uirenderer::ResourceCache::getInstance().destructor(p);
return;
}
#endif // USE_OPENGL_RENDERER
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 9d3e74b..30ce58d 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -27,7 +27,7 @@
#include "SkPath.h"
#include "SkPathOps.h"
-#include <Caches.h>
+#include <ResourceCache.h>
#include <vector>
#include <map>
@@ -39,8 +39,8 @@ public:
static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
#ifdef USE_OPENGL_RENDERER
- if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().resourceCache.destructor(obj);
+ if (android::uirenderer::ResourceCache::hasInstance()) {
+ android::uirenderer::ResourceCache::getInstance().destructor(obj);
return;
}
#endif
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 9ec9993..178bab6 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -46,10 +46,12 @@ enum {
HEAP_UNKNOWN,
HEAP_DALVIK,
HEAP_NATIVE,
+
HEAP_DALVIK_OTHER,
HEAP_STACK,
HEAP_CURSOR,
HEAP_ASHMEM,
+ HEAP_GL_DEV,
HEAP_UNKNOWN_DEV,
HEAP_SO,
HEAP_JAR,
@@ -297,7 +299,11 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
} else if (strncmp(name, "[stack", 6) == 0) {
whichHeap = HEAP_STACK;
} else if (strncmp(name, "/dev/", 5) == 0) {
- whichHeap = HEAP_UNKNOWN_DEV;
+ if (strncmp(name, "/dev/kgsl-3d0", 13) == 0) {
+ whichHeap = HEAP_GL_DEV;
+ } else {
+ whichHeap = HEAP_UNKNOWN_DEV;
+ }
} else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) {
whichHeap = HEAP_SO;
is_swappable = true;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6f2a06b..ffe2b60 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2511,11 +2511,12 @@
android:description="@string/permdesc_broadcastWapPush"
android:protectionLevel="signature" />
- <!-- @SystemApi Allows an application to broadcast a SCORE_NETWORKS request.
+ <!-- @SystemApi Allows an application to broadcast privileged networking requests.
<p>Not for use by third-party applications. @hide -->
- <permission android:name="android.permission.BROADCAST_SCORE_NETWORKS"
- android:label="@string/permlab_broadcastScoreNetworks"
- android:description="@string/permdesc_broadcastScoreNetworks"
+ <permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED"
+ android:permissionGroup="android.permission-group.NETWORK"
+ android:label="@string/permlab_broadcastNetworkPrivileged"
+ android:description="@string/permdesc_broadcastNetworkPrivileged"
android:protectionLevel="signature|system" />
<!-- @SystemApi Not for use by third-party applications. -->
diff --git a/core/res/res/drawable-hdpi/sym_def_app_icon.png b/core/res/res/drawable-hdpi/sym_def_app_icon.png
index 96a442e..cde69bc 100644
--- a/core/res/res/drawable-hdpi/sym_def_app_icon.png
+++ b/core/res/res/drawable-hdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_def_app_icon.png b/core/res/res/drawable-mdpi/sym_def_app_icon.png
index 359047d..c133a0c 100644
--- a/core/res/res/drawable-mdpi/sym_def_app_icon.png
+++ b/core/res/res/drawable-mdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_def_app_icon.png b/core/res/res/drawable-xhdpi/sym_def_app_icon.png
index 71c6d76..bfa42f0 100644
--- a/core/res/res/drawable-xhdpi/sym_def_app_icon.png
+++ b/core/res/res/drawable-xhdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_def_app_icon.png b/core/res/res/drawable-xxhdpi/sym_def_app_icon.png
index 20a47a0..324e72c 100644
--- a/core/res/res/drawable-xxhdpi/sym_def_app_icon.png
+++ b/core/res/res/drawable-xxhdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/sym_def_app_icon.png b/core/res/res/drawable-xxxhdpi/sym_def_app_icon.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon.png b/core/res/res/mipmap-hdpi/sym_def_app_icon.png
index c8a38ed..cde69bc 100644
--- a/core/res/res/mipmap-hdpi/sym_def_app_icon.png
+++ b/core/res/res/mipmap-hdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon.png b/core/res/res/mipmap-mdpi/sym_def_app_icon.png
index b3e10f6..c133a0c 100644
--- a/core/res/res/mipmap-mdpi/sym_def_app_icon.png
+++ b/core/res/res/mipmap-mdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon.png
index f381f86..bfa42f0 100644
--- a/core/res/res/mipmap-xhdpi/sym_def_app_icon.png
+++ b/core/res/res/mipmap-xhdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon.png
index e3f3144..324e72c 100644
--- a/core/res/res/mipmap-xxhdpi/sym_def_app_icon.png
+++ b/core/res/res/mipmap-xxhdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index bb9885c..f6a5787 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -441,4 +441,13 @@
<item>中文 (繁體)</item>
</string-array>
+ <array name="sim_colors">
+ <item>@color/Teal_700</item>
+ <item>@color/Blue_700</item>
+ <item>@color/Indigo_700</item>
+ <item>@color/Purple_700</item>
+ <item>@color/Pink_700</item>
+ <item>@color/Red_700</item>
+ </array>
+
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 91a8598..67ba27da 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6388,7 +6388,7 @@
<!-- The summary for the Preference in a PreferenceActivity screen. -->
<attr name="summary" />
<!-- The order for the Preference (lower values are to be ordered first). If this is not
- specified, the default orderin will be alphabetic. -->
+ specified, the default ordering will be alphabetic. -->
<attr name="order" format="integer" />
<!-- When used inside of a modern PreferenceActivity, this declares
a new PreferenceFragment to be shown when the user selects this item. -->
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 9f83db4..b9825c5 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -160,5 +160,18 @@
<color name="user_icon_8">#ffff5722</color><!-- deep orange 500 -->
<color name="user_icon_default_gray">#ff9e9e9e</color><!-- gray 500 -->
<color name="user_icon_default_white">#ffffffff</color><!-- white -->
-</resources>
+ <!-- Multi-sim sim colors -->
+ <color name="Teal_700">#ff00796b</color>
+ <color name="Teal_800">#ff00695c</color>
+ <color name="Blue_700">#ff3367d6</color>
+ <color name="Blue_800">#ff2a56c6</color>
+ <color name="Indigo_700">#ff303f9f</color>
+ <color name="Indigo_800">#ff283593</color>
+ <color name="Purple_700">#ff7b1fa2</color>
+ <color name="Purple_800">#ff6a1b9a</color>
+ <color name="Pink_700">#ffc2185b</color>
+ <color name="Pink_800">#ffad1457</color>
+ <color name="Red_700">#ffc53929</color>
+ <color name="Red_800">#ffb93221</color>
+</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1534b49..52ef4f9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -473,6 +473,8 @@
<bool name="config_allowTheaterModeWakeFromDock">false</bool>
<!-- If this is true, allow wake from theater mode from window layout flag. -->
<bool name="config_allowTheaterModeWakeFromWindowLayout">false</bool>
+ <!-- If this is true, go to sleep when theater mode is enabled from button press -->
+ <bool name="config_goToSleepOnButtonPressTheaterMode">true</bool>
<!-- Auto-rotation behavior -->
@@ -801,6 +803,13 @@
that can be set by the user. -->
<integer name="config_screenBrightnessDoze">1</integer>
+ <!-- Allow automatic adjusting of the screen brightness while dozing in low power state. -->
+ <bool name="config_allowAutoBrightnessWhileDozing">false</bool>
+
+ <!-- If we allow automatic adjustment of screen brightness while dozing, how many times we want
+ to reduce it to preserve the battery. Value of 100% means no scaling. -->
+ <fraction name="config_screenAutoBrightnessDozeScaleFactor">100%</fraction>
+
<!-- Screen brightness used to dim the screen when the user activity
timeout expires. May be less than the minimum allowed brightness setting
that can be set by the user. -->
@@ -1907,4 +1916,7 @@
1. Lenient threshold
-->
<integer name="config_LTE_RSRP_threshold_type">1</integer>
+
+ <!-- Show the next-alarm as a zen exit condition if it occurs in the next n hours. -->
+ <integer name="config_next_alarm_condition_lookahead_threshold_hrs">12</integer>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 61fc161..9e25ee2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -61,6 +61,9 @@
<!-- [CHAR_LIMIT=10] Suffix added to signify duration in minutes -->
<string name="durationMinutes"><xliff:g id="minutes">%1$d</xliff:g> mins</string>
+ <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one minute -->
+ <string name="durationMinute"><xliff:g id="minutes">%1$d</xliff:g> min</string>
+
<!-- [CHAR_LIMIT=10] Suffix added to signify duration of one minute with seconds -->
<string name="durationMinuteSeconds"><xliff:g id="minutes">%1$d</xliff:g> min
<xliff:g id="seconds">%2$d</xliff:g> secs</string>
@@ -977,10 +980,10 @@
<!-- TODO: Mark these as translatable when API is finalized. -->
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_broadcastScoreNetworks" translatable="false">send score networks broadcast</string>
+ <string name="permlab_broadcastNetworkPrivileged" translatable="false">send privileged network broadcasts</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_broadcastScoreNetworks" translatable="false">Allows the app
- to broadcast a notification that networks need to be scored.
+ <string name="permdesc_broadcastNetworkPrivileged" translatable="false">Allows the app
+ to send privileged network broadcasts.
Never needed for normal apps.
</string>
@@ -4879,7 +4882,10 @@
<string name="battery_saver_description">To help improve battery life, battery saver reduces your device’s performance and limits vibration and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging.</string>
<!-- [CHAR_LIMIT=NONE] Zen mode: Condition summary for built-in downtime condition, if active -->
- <string name="downtime_condition_summary">Until your downtime ends at <xliff:g id="formattedTime" example="10.00 PM">%1$s</xliff:g></string>
+ <string name="downtime_condition_summary">Until your downtime ends at <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g></string>
+
+ <!-- [CHAR_LIMIT=NONE] Zen mode: Condition line one for built-in downtime condition, if active -->
+ <string name="downtime_condition_line_one">Until your downtime ends</string>
<!-- Zen mode condition - summary: time duration in minutes. [CHAR LIMIT=NONE] -->
<plurals name="zen_mode_duration_minutes_summary">
@@ -4913,4 +4919,10 @@
<!-- Content description for the Toolbar icon used to collapse an expanded action mode. [CHAR LIMIT=NONE] -->
<string name="toolbar_collapse_description">Collapse</string>
+
+ <!-- Zen mode condition - summary: until next alarm. [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_next_alarm_summary">Until next alarm at <xliff:g id="formattedTime" example="7:30 AM">%1$s</xliff:g></string>
+
+ <!-- Zen mode condition - line one: until next alarm. [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_next_alarm_line_one">Until next alarm</string>
</resources>
diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml
index 0c854d3..cf90b39 100644
--- a/core/res/res/values/styles_micro.xml
+++ b/core/res/res/values/styles_micro.xml
@@ -25,6 +25,14 @@
<item name="taskOpenExitAnimation">@null</item>
<item name="taskCloseEnterAnimation">@null</item>
<item name="taskCloseExitAnimation">@anim/slide_out_micro</item>
+ <item name="wallpaperOpenEnterAnimation">@null</item>
+ <item name="wallpaperOpenExitAnimation">@anim/slide_out_micro</item>
+ <item name="wallpaperCloseEnterAnimation">@anim/slide_in_micro</item>
+ <item name="wallpaperCloseExitAnimation">@null</item>
+ <item name="wallpaperIntraOpenEnterAnimation">@null</item>
+ <item name="wallpaperIntraOpenExitAnimation">@anim/slide_out_micro</item>
+ <item name="wallpaperIntraCloseEnterAnimation">@anim/slide_in_micro</item>
+ <item name="wallpaperIntraCloseExitAnimation">@null</item>
</style>
<style name="AlertDialog.Micro" parent="AlertDialog.Holo.Light">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3835d8b..513510a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -574,6 +574,7 @@
<java-symbol type="string" name="durationHourMinutes" />
<java-symbol type="string" name="durationHourMinute" />
<java-symbol type="string" name="durationMinutes" />
+ <java-symbol type="string" name="durationMinute" />
<java-symbol type="string" name="durationMinuteSeconds" />
<java-symbol type="string" name="durationMinuteSecond" />
<java-symbol type="string" name="durationSeconds" />
@@ -1073,6 +1074,7 @@
<java-symbol type="array" name="networkAttributes" />
<java-symbol type="array" name="preloaded_color_state_lists" />
<java-symbol type="array" name="preloaded_drawables" />
+ <java-symbol type="array" name="sim_colors" />
<java-symbol type="array" name="special_locale_codes" />
<java-symbol type="array" name="special_locale_names" />
<java-symbol type="array" name="config_masterVolumeRamp" />
@@ -1574,6 +1576,7 @@
<java-symbol type="bool" name="config_enableNetworkLocationOverlay" />
<java-symbol type="bool" name="config_sf_limitedAlpha" />
<java-symbol type="bool" name="config_unplugTurnsOnScreen" />
+ <java-symbol type="bool" name="config_allowAutoBrightnessWhileDozing" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromUnplug" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromGesture" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromCameraLens" />
@@ -1583,6 +1586,7 @@
<java-symbol type="bool" name="config_allowTheaterModeWakeFromLidSwitch" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromDock" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromWindowLayout" />
+ <java-symbol type="bool" name="config_goToSleepOnButtonPressTheaterMode" />
<java-symbol type="bool" name="config_wifi_background_scan_support" />
<java-symbol type="bool" name="config_wifi_dual_band_support" />
<java-symbol type="bool" name="config_wimaxEnabled" />
@@ -1615,6 +1619,7 @@
<java-symbol type="id" name="replace_app_icon" />
<java-symbol type="id" name="replace_message" />
<java-symbol type="fraction" name="config_dimBehindFadeDuration" />
+ <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
<java-symbol type="integer" name="config_carDockKeepsScreenOn" />
<java-symbol type="integer" name="config_criticalBatteryWarningLevel" />
<java-symbol type="integer" name="config_datause_notification_type" />
@@ -1984,12 +1989,16 @@
<java-symbol type="string" name="timepicker_transition_end_radius_multiplier" />
<java-symbol type="string" name="battery_saver_description" />
<java-symbol type="string" name="downtime_condition_summary" />
+ <java-symbol type="string" name="downtime_condition_line_one" />
<java-symbol type="string" name="zen_mode_forever" />
<java-symbol type="plurals" name="zen_mode_duration_minutes" />
<java-symbol type="plurals" name="zen_mode_duration_hours" />
<java-symbol type="plurals" name="zen_mode_duration_minutes_summary" />
<java-symbol type="plurals" name="zen_mode_duration_hours_summary" />
<java-symbol type="string" name="zen_mode_until" />
+ <java-symbol type="string" name="zen_mode_next_alarm_summary" />
+ <java-symbol type="string" name="zen_mode_next_alarm_line_one" />
+ <java-symbol type="integer" name="config_next_alarm_condition_lookahead_threshold_hrs" />
<java-symbol type="string" name="item_is_selected" />
<java-symbol type="string" name="day_of_week_label_typeface" />
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index f916711..9bb44d0 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -59,7 +59,7 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
// Package 1 - Valid scorer.
Pair<ResolveInfo, ResolveInfo> package1 = buildResolveInfo("package1", true, true, false);
- // Package 2 - Receiver does not have BROADCAST_SCORE_NETWORKS permission.
+ // Package 2 - Receiver does not have BROADCAST_NETWORK_PRIVILEGED permission.
Pair<ResolveInfo, ResolveInfo> package2 = buildResolveInfo("package2", false, true, false);
// Package 3 - App does not have SCORE_NETWORKS permission.
@@ -134,7 +134,7 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
resolveInfo.activityInfo.packageName = packageName;
resolveInfo.activityInfo.applicationInfo = new ApplicationInfo();
if (hasReceiverPermission) {
- resolveInfo.activityInfo.permission = permission.BROADCAST_SCORE_NETWORKS;
+ resolveInfo.activityInfo.permission = permission.BROADCAST_NETWORK_PRIVILEGED;
}
ResolveInfo configActivityInfo = null;
diff --git a/docs/html/about/about_toc.cs b/docs/html/about/about_toc.cs
index c025b61..9033d69 100644
--- a/docs/html/about/about_toc.cs
+++ b/docs/html/about/about_toc.cs
@@ -11,6 +11,7 @@
<span class="en">Lollipop</span></a></div>
<ul>
<li><a href="<?cs var:toroot ?>about/versions/android-5.0.html">Android 5.0 APIs</a></li>
+ <li><a href="<?cs var:toroot ?>about/versions/android-5.0-changes.html">Android 5.0 Changes</a></li>
</ul>
</li>
<li class="nav-section">
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 808f04a..448dcda 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -41,13 +41,6 @@ with Android 2.2 and higher. Each snapshot of data represents all the devices th
Google Play Store in the prior 7 days.</p>
-<div class="note">
-<p><strong>Note:</strong> Beginning in September, 2013, devices running versions older than Android
-2.2 do not appear in this data because those devices do not support the new Google Play Store
-app. Only the new app is able to measure the number of devices that actively visit Google Play Store
-and we believe this measurement best reflects your potential user-base.</p>
-</div>
-
<h2 id="Platform">Platform Versions</h2>
@@ -64,7 +57,7 @@ Platform Versions</a>.</p>
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on September 9, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on November 3, 2014.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -95,7 +88,7 @@ Screens</a>.</p>
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on September 9, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on November 3, 2014.
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -115,7 +108,7 @@ support for any lower version (for example, support for version 2.0 also implies
<img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A77.5%2C22.5&chf=bg%2Cs%2C00000000&chl=GL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
+src="//chart.googleapis.com/chart?chl=GL%202.0%7CGL%203.0&chd=t%3A74.7%2C25.3&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250" />
<p>To declare which version of OpenGL ES your application requires, you should use the {@code
android:glEsVersion} attribute of the <a
@@ -133,17 +126,17 @@ uses.</p>
</tr>
<tr>
<td>2.0</td>
-<td>77.5%</td>
+<td>74.7%</td>
</tr>
<tr>
<td>3.0</td>
-<td>22.5%</td>
+<td>25.3%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on September 9, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on November 3, 2014</em></p>
@@ -161,42 +154,42 @@ uses.</p>
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&cht=p&chs=500x250&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A0.7%2C11.4%2C9.6%2C53.8%2C24.5&chf=bg%2Cs%2C00000000",
+ "chart": "//chart.googleapis.com/chart?chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A0.6%2C9.8%2C8.5%2C50.9%2C30.2&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=500x250",
"data": [
{
"api": 8,
"name": "Froyo",
- "perc": "0.7"
+ "perc": "0.6"
},
{
"api": 10,
"name": "Gingerbread",
- "perc": "11.4"
+ "perc": "9.8"
},
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "9.6"
+ "perc": "8.5"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "25.1"
+ "perc": "22.8"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "20.7"
+ "perc": "20.8"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "8.0"
+ "perc": "7.3"
},
{
"api": 19,
"name": "KitKat",
- "perc": "24.5"
+ "perc": "30.2"
}
]
}
@@ -210,27 +203,27 @@ var SCREEN_DATA =
"Large": {
"hdpi": "0.6",
"ldpi": "0.5",
- "mdpi": "4.3",
- "tvdpi": "1.7",
+ "mdpi": "4.5",
+ "tvdpi": "1.9",
"xhdpi": "0.6"
},
"Normal": {
- "hdpi": "35.7",
- "mdpi": "10.6",
- "xhdpi": "19.2",
- "xxhdpi": "16.2"
+ "hdpi": "36.6",
+ "mdpi": "9.9",
+ "xhdpi": "18.9",
+ "xxhdpi": "16.0"
},
"Small": {
- "ldpi": "6.2"
+ "ldpi": "5.8"
},
"Xlarge": {
"hdpi": "0.3",
- "mdpi": "3.7",
- "xhdpi": "0.4"
+ "mdpi": "3.9",
+ "xhdpi": "0.5"
}
},
- "densitychart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&cht=p&chs=400x250&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A6.7%2C18.6%2C1.7%2C36.6%2C20.2%2C16.2&chf=bg%2Cs%2C00000000",
- "layoutchart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&cht=p&chs=400x250&chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.4%2C7.7%2C81.7%2C6.2&chf=bg%2Cs%2C00000000"
+ "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A6.3%2C18.3%2C1.9%2C37.5%2C20.0%2C16.0&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250",
+ "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.7%2C8.1%2C81.4%2C5.8&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250"
}
];
@@ -302,6 +295,16 @@ var VERSION_NAMES =
"api":19,
"link":"<a href='/about/versions/android-4.4.html'>4.4</a>",
"codename":"KitKat"
+ },
+ {
+ "api":20,
+ "link":"<a href='/about/versions/android-4.4.html'>4.4W</a>",
+ "codename":"KitKat for Wear"
+ },
+ {
+ "api":21,
+ "link":"<a href='/about/versions/android-5.0.html'>4.4</a>",
+ "codename":"Lollipop"
}
];
diff --git a/docs/html/about/versions/android-5.0-changes.jd b/docs/html/about/versions/android-5.0-changes.jd
new file mode 100644
index 0000000..c1b9f09
--- /dev/null
+++ b/docs/html/about/versions/android-5.0-changes.jd
@@ -0,0 +1,527 @@
+page.title=Android 5.0 Changes
+excludeFromSuggestions=true
+sdk.platform.version=5.0
+sdk.platform.apiLevel=21
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+<ol id="toc44" class="hide-nested">
+ <li><a href="#UI"><a href="#ART">ART Runtime</a></a></li>
+ <li><a href="#BehaviorNotifications">Notifications</a></li>
+ <li><a href="#BehaviorMediaControl">Media Controls</a></li>
+ <li><a href="#BehaviorGetRecentTasks">getRecentTasks()</a></li>
+ <li><a href="#64BitSupport">64-Bit Android NDK</a></li>
+ <li><a href="#BindService">Binding to a Service</a></li>
+ <li><a href="#Power"><a href="#BehaviorWebView">WebView</a></a></li>
+ <li><a href="#custom_permissions">Custom Permissions</a></li>
+ <li><a href="#ssl">TLS/SSL Configuration</a></li>
+</ol>
+
+<h2>API Differences</h2>
+<ol>
+<li><a href="{@docRoot}sdk/api_diff/21/changes.html">API level 20 to 21 &raquo;</a> </li>
+<li><a href="{@docRoot}sdk/api_diff/preview-21/changes.html">L Developer Preview to 21 &raquo;</a> </li>
+</ol>
+
+
+<h2>See Also</h2>
+<ol>
+<li><a href="{@docRoot}about/versions/lollipop.html">Android Lollipop Highlights</a> </li>
+<li><a href="{@docRoot}about/versions/android-5.0.html">Android 5.0 API Overview</a> </li>
+</ol>
+
+
+</div>
+</div>
+
+<p>API Level: {@sdkPlatformApiLevel}</p>
+<p>Along with new features and capabilities, Android 5.0 includes a variety of changes
+API changes,
+behavior changes, system enhancements, and bug fixes. This document highlights
+some of the key changes that you should be understand and account for in your apps.</p>
+
+<p>f you have previously published an app for Android, be aware that your app
+ might be affected by these changes in Android 5.0.</p>
+
+
+<p>For a high-level look at the new platform features, instead
+see the
+<a href="{@docRoot}about/versions/lollipop.html">Android Lollipop
+highlights</a>.</p>
+
+
+
+<h2 id="ART">Android Runtime (ART)</h2>
+
+<p>In Android 5.0 the ART runtime replaces Dalvik as the platform default. The ART runtime was
+introduced in Android 4.4 on an experimental basis.</p>
+
+<p>For an overview of ART's new features, see
+<a href="https://source.android.com/devices/tech/dalvik/art.html">Introducing
+ART</a>. Some of the major new features are:</p>
+
+<ul>
+ <li>Ahead-of-time (AOT) compilation</li>
+ <li>Improved garbage collection (GC)</li>
+ <li>Improved debugging support</li>
+</ul>
+
+<p>Most Android apps should just work without any changes under ART. However, some
+techniques that work on Dalvik do not work on ART. For information about the
+most important issues, see
+<a href="{@docRoot}guide/practices/verifying-apps-art.html">Verifying App
+Behavior on the Android Runtime (ART)</a>. Pay particular attention if:</p>
+
+<ul>
+ <li>Your app uses Java Native Interface (JNI) to run C/C++ code.</li>
+ <li>You use development tools that generate non-standard code (such as some
+ obfuscators).</li>
+ <li>You use techniques that are incompatible with compacting garbage
+ collection. (ART does not currently implement compacting GC, but
+ compacting GC is under development in the Android Open Source
+ Project.)</li>
+</ul>
+
+
+<h2 id="BehaviorNotifications">Notifications</h2>
+
+<p>Make sure your notifications take these Android 5.0 changes into account.
+ To learn more about designing your notifications for Android 5.0 and higher,
+ see the <a href="{@docRoot}design/patterns/notifications.html">notifications design guide</a>.
+</p>
+
+<h3 id="NotificationsMaterialDesignStyle">Material design style</h3>
+<p>Notifications are drawn with dark text atop white (or very light) backgrounds
+ to match the new material design widgets. Make sure that all your
+ notifications look right with the new color scheme. If your notifications
+look wrong, fix them:</p>
+
+<ul>
+ <li>Use {@link android.app.Notification.Builder#setColor(int) setColor()}
+ to set an accent color in a circle behind your icon image. </li>
+ <li>Update or remove assets that involve color. The system ignores all
+ non-alpha channels in action icons and in the main notification icon. You
+ should assume that these icons will be alpha-only. The system draws
+ notification icons in white and action icons in dark gray.</li>
+</ul>
+
+<h3 id="NotificationsSoundVibration">Sound and vibration</h3>
+<p>If you are currently adding sounds and vibrations to your notifications by
+using the {@link android.media.Ringtone}, {@link android.media.MediaPlayer},
+or {@link android.os.Vibrator} classes, remove this code so that
+the system can present notifications correctly in
+<em>priority</em> mode. Instead, use
+{@link android.app.Notification.Builder} methods to add sounds and
+vibration.</p>
+
+<p>Setting the device to
+{@link android.media.AudioManager#RINGER_MODE_SILENT RINGER_MODE_SILENT} causes
+the device to enter the new priority mode. The device leaves priority
+mode if you set it to
+{@link android.media.AudioManager#RINGER_MODE_NORMAL RINGER_MODE_NORMAL} or
+{@link android.media.AudioManager#RINGER_MODE_NORMAL RINGER_MODE_VIBRATE}.</p>
+
+<p>Previously, Android used {@link android.media.AudioManager#STREAM_MUSIC STREAM_MUSIC}
+as the master stream to control volume on tablet devices. In Android 5.0, the
+master volume stream for both phone and tablet devices is now unified, and
+is controlled by {@link android.media.AudioManager#STREAM_RING STREAM_RING} or
+{@link android.media.AudioManager#STREAM_NOTIFICATION STREAM_NOTIFICATION}.</p>
+
+<h3 id="NotificationsLockscreenVisibility">Lock screen visibility</h3>
+<p>By default, notifications now appear on the user's lock screen in Android 5.0.
+Users can choose to protect sensitive information from being exposed, in which
+case the system automatically redacts the text displayed by the notification. To
+customize this redacted notification, use
+{@link android.app.Notification.Builder#setPublicVersion(android.app.Notification)
+ setPublicVersion()}.</p>
+<p>If the notification does not contain personal information, or if you want to
+allow media playback control on the notification, call the
+{@link android.app.Notification.Builder#setVisibility(int) setVisibility()}
+method and set the notification's visibility level to
+{@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC}.
+</p>
+
+<h3 id="NotificationsMediaPlayback">Media playback</h3>
+<p>If you are implementing notifications that present media playback
+status or transport controls, consider using the new
+{@link android.app.Notification.MediaStyle} template instead of a custom
+{@link android.widget.RemoteViews.RemoteView} object. Whichever approach you
+choose, make sure to set the notification's visibility to
+{@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC} so that
+your controls are accessible from the lock screen. Note that beginning in
+Android 5.0, the system no longer shows
+{@link android.media.RemoteControlClient} objects on the lock screen. For more
+information, see
+<a href="#BehaviorMediaControl">If your app uses RemoteControlClient</a>.</p>
+
+<h3 id="NotificationsHeadsup">Heads-up notification</h3>
+<p>Notifications may now appear in a small floating window (also called a
+ heads-up notification) when the device is active (that is, the device is
+ unlocked and its screen is on). These notifications appear similar to the
+ compact form of your notification, except that the heads-up notification also
+ shows action buttons. Users can act on, or dismiss, a heads-up notification
+ without leaving the current app.</p>
+
+<p>Examples of conditions that may trigger heads-up notifications include:</p>
+
+<ul>
+ <li>The user's activity is in fullscreen mode (the app uses
+{@link android.app.Notification#fullScreenIntent})</li>
+ <li>The notification has high priority and uses ringtones or vibrations</li>
+</ul>
+
+<p>If your app implements notifications under any of those scenarios, make sure
+that heads-up notifications are presented correctly.</p>
+
+<h2 id="BehaviorMediaControl">Media Controls and RemoteControlClient</h2>
+<p>The {@link android.media.RemoteControlClient} class is now deprecated. Switch
+ to the new {@link android.media.session.MediaSession} API as
+ soon as possible.</p>
+
+<p>Lock screens in Android 5.0 do not show transport controls for
+your {@link android.media.session.MediaSession} or
+{@link android.media.RemoteControlClient}. Instead, your app can provide
+media playback control from the lock screen through a notification. This
+gives your app more control over the presentation of media buttons, while
+providing a consistent experience for users across locked and
+unlocked devices.</p>
+
+<p>Android 5.0 introduces a new
+{@link android.app.Notification.MediaStyle} template for this purpose.
+{@link android.app.Notification.MediaStyle} converts notification
+actions that you added with
+{@link android.app.Notification.Builder#addAction(int, java.lang.CharSequence,
+ android.app.PendingIntent)
+Notification.Builder.addAction()} into compact buttons embedded in your app's
+media playback notifications. Pass your session token to the
+{@link android.app.Notification.MediaStyle#setMediaSession(android.media.session.MediaSession.Token)
+ setSession()} method to inform the system that this notification controls an
+ ongoing media session.</p>
+
+<p>Make sure to set the notification's visibility to
+ {@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC}
+ to mark the notification as safe to show on any lock screen (secure or
+ otherwise). For more information, see
+ <a href="#LockscreenNotifications">Lock screen notifications</a>.</p>
+
+<p>To display media playback controls if your app is running on the
+Android <a href="{@docRoot}tv/index.html">TV</a> or
+<a href="{@docRoot}wear/index.html">Wear</a> platform, implement the
+{@link android.media.session.MediaSession} class. You should also implement
+{@link android.media.session.MediaSession} if your app needs to receive media
+button events on Android devices.</p>
+
+<h2 id="BehaviorGetRecentTasks">getRecentTasks()</h2>
+
+<p>With the introduction of the new <em>concurrent documents and activities
+tasks</em> feature in Android 5.0 (see <a href="#Recents">Concurrent
+documents and activities in the recents screen</a> below),
+the {@link android.app.ActivityManager#getRecentTasks
+ActivityManager.getRecentTasks()} method is now deprecated to improve user
+privacy. For backward compatibility, this method still returns a small subset of
+its data, including the calling application’s own tasks and possibly some other
+non-sensitive tasks (such as Home). If your app is using this method to retrieve
+its own tasks, use {@link android.app.ActivityManager#getAppTasks() getAppTasks()}
+instead to retrieve that information.</p>
+
+<h2 id="64BitSupport">64-Bit Support in the Android NDK</h2>
+
+<p>Android 5.0 introduces support for 64-bit systems. The 64-bit enhancement
+ increases address space and improves performance, while still supporting
+ existing 32-bit apps fully. The 64-bit support also improves the performance of
+ OpenSSL for cryptography. In addition, this release introduces new native
+ media NDK APIs, as well as native OpenGL ES (GLES) 3.1 support.</p>
+
+<p>To use the 64-bit support provided in Android 5.0, download and install NDK
+ Revision 10c from the
+<a href="{@docRoot}tools/sdk/ndk/index.html">Android NDK page</a>. Refer to the
+Revision 10c <a href="{@docRoot}tools/sdk/ndk/index.html#Revisions">release notes</a>
+for more information about important changes and bug fixes to the NDK.</p>
+
+<h2 id="BindService">Binding to a Service</h2>
+
+<p>The
+ {@link android.content.Context#bindService(android.content.Intent, android.content.ServiceConnection, int) Context.bindService()}
+ method now requires an explicit {@link android.content.Intent},
+and throws an exception if given an implicit intent.
+To ensure your app is secure, use an explicit intent when starting or binding
+your {@link android.app.Service}, and do not declare intent filters for the service.</p>
+
+<h2 id="BehaviorWebView">WebView</h2>
+
+<p>Android 5.0 changes the default behavior for your app.</p>
+<ul>
+<li><strong>If your app targets API level 21 or higher:</strong>
+ <ul>
+ <li>The system
+ blocks <a href="https://developer.mozilla.org/en-US/docs/Security/MixedContent"
+ class="external-link">mixed content</a> and third party cookies by default. To allow mixed
+ content and third party cookies, use the
+ {@link android.webkit.WebSettings#setMixedContentMode(int) setMixedContentMode()}
+and {@link android.webkit.CookieManager#setAcceptThirdPartyCookies(android.webkit.WebView, boolean) setAcceptThirdPartyCookies()}
+methods respectively.</li>
+ <li>The system now intelligently chooses portions of the HTML
+ document to draw. This new default behavior helps to reduce memory
+ footprint and increase performance. If you want to
+ render the whole document at once, disable this optimization by calling
+ {@link android.webkit.WebView#enableSlowWholeDocumentDraw()}.</li>
+ </ul>
+</li>
+<li><strong>If your app targets API levels lower than 21:</strong> The system
+ allows mixed content and third party cookies, and always renders the whole
+ document at once.</li>
+</ul>
+
+<h2 id="custom_permissions">Uniqueness Requirement for Custom Permissions</h2>
+
+<p>
+ As documented in the <a href=
+ "{@docRoot}guide/topics/manifest/manifest-intro.html#perms">Permissions</a>
+ overview, Android apps can define custom permissions as a means of managing
+ access to components in a proprietary way, without using the platform’s
+ pre-defined system permissions. Apps define custom permissions in <a href=
+ "http://developer.android.com/guide/topics/manifest/permission-element.html"><code>
+ &lt;permission&gt;</code></a> elements declared in their manifest files.
+</p>
+
+<p>
+ There are a small number of scenarios where defining custom permissions is a
+ legitimate and secure approach. However, creating custom permissions is
+ sometimes unnecessary and can even introduce potential risk to an app,
+ depending on the protection level assigned to the permissions.
+</p>
+
+<p>
+ Android 5.0 includes a behavior change to ensure
+ that only one app can define a given custom permission, unless signed with the
+ same key as other apps defining the permission.
+</p>
+
+<h3>
+ Apps using duplicate custom permissions
+</h3>
+
+<p>
+ Any app can define any custom permission it wants, so it can happen
+ that multiple apps might <strong>define the same custom permission</strong>.
+ For example, if two apps offer a similar capability, they might derive the
+ same logical name for their custom permissions. Apps might also incorporate
+ common public libraries or code examples that themselves include the same
+ custom permission definitions.
+</p>
+
+<p>
+ In Android 4.4 and earlier, users were able to install multiple such
+ apps on a given device, although the system assigned the protection level
+ specified by the first-installed app.
+</p>
+
+<p>
+ Starting in Android 5.0, the system enforces a new
+ <strong>uniqueness restriction on custom permissions</strong> for
+ apps that are signed with different keys. Now only one app on a device can
+ define a given custom permission (as determined by its name), unless the
+ other app defining the permission is signed with the same key. If the user
+ tries to install an app with a duplicate custom permission and is not signed
+ with the same key as the resident app that defines the permission, the system
+ blocks the installation.
+</p>
+
+<h3>
+ Considerations for your app
+</h3>
+
+<p>
+ In Android 5.0 and later, apps can continue to define their own custom
+ permissions just as before and to request custom permissions from other apps
+ through the <code>&lt;uses-permission&gt;</code> mechanism. However with the
+ new requirement introduced in Android 5.0, you should carefully assess
+ possible impacts on your app.
+</p>
+
+<p>
+ Here are some points to consider:
+</p>
+
+<ul>
+ <li>Does your app declare any <a href=
+ "http://developer.android.com/guide/topics/manifest/permission-element.html">
+ <code>&lt;permission&gt;</code></a> elements in its manifest? If so, are
+ they actually necessary to the proper function of your app or service? Or
+ could you use a system default permission instead?
+ </li>
+
+ <li>If you have <a href=
+ "http://developer.android.com/guide/topics/manifest/permission-element.html">
+ <code>&lt;permission&gt;</code></a> elements in your app, do you know where
+ they came from?
+ </li>
+
+ <li>Do you actually intend for other apps to request your custom permissions
+ through <a href=
+ "http://developer.android.com/guide/topics/manifest/uses-permission-element.html">
+ <code>&lt;uses-permission&gt;</code></a>?
+ </li>
+
+ <li>Are you using boilerplate or example code in your app that includes
+ <a href=
+ "http://developer.android.com/guide/topics/manifest/permission-element.html">
+ <code>&lt;permission&gt;</code></a> elements? Are those permission elements
+ actually necessary?
+ </li>
+
+ <li>Do your custom permissions use names that are simple or based on common
+ terms that other apps might share?
+ </li>
+</ul>
+
+<h3>
+ New installs and updates
+</h3>
+
+<p>
+ As mentioned above, for new installs and updates of your app on devices
+ running Android 4.4 or earlier are unaffected and there is no change in
+ behavior. For new installs and updates on devices running Android 5.0 or
+ later, the system <strong>prevents installation of your app</strong> if it
+ defines a custom permission that is already defined by an existing resident
+ app.
+</p>
+
+<h3>
+ Existing installs with Android 5.0 system update
+</h3>
+
+<p>
+ If your app uses custom permissions and is widely distributed and installed,
+ there’s a chance that it will be affected when users receive update their
+ devices to Android 5.0. After the system update is installed, the system
+ revalidates installed apps, including a check of their custom permissions. If
+ your app defines a custom permission that is already defined by another app
+ that has already been validated, and your app is not signed with the same key
+ as the other app, the system <strong>does not re-install your app</strong>.
+</p>
+
+<h3>
+ Recommendations
+</h3>
+
+<p>
+ On devices running Android 5.0 or later, we recommend that you examine your
+ app immediately, make any adjustments needed, and publish the updated version
+ as soon as possible to your users.
+</p>
+
+<ul>
+ <li>If you are using custom permissions in your app, consider their origin
+ and whether you actually need them. Remove all <a href=
+ "http://developer.android.com/guide/topics/manifest/permission-element.html">
+ <code>&lt;permission&gt;</code></a> elements from your app, unless you are
+ certain that they are required for proper function of your app.
+ </li>
+
+ <li>Consider replacing your custom permissions with system default
+ permissions where possible.
+ </li>
+
+ <li>If your app requires custom permissions, rename your custom permissions
+ to be unique to your app, such as by appending them to the full package name
+ of your app.
+ </li>
+
+ <li>If you have a suite of apps <em>signed with different keys</em> and the apps
+ access a shared component by means of a custom permission, make sure that the
+ custom permission is only defined once, in the shared component. Apps that
+ use the shared component should not define the custom permission themselves,
+ but should instead request access through the <a href=
+ "{@docRoot}guide/topics/manifest/uses-permission-element.html">
+ <code>&lt;uses-permission&gt;</code></a> mechanism.
+ </li>
+
+ <li>If you have a suite of apps are <em>signed with the same key</em>,
+ each app can define the same custom permission(s) as <span style="white-space:nowrap;">needed
+ &mdash; the</span> system allows the apps to be installed in the usual way.
+ </li>
+
+</ul>
+
+
+<h2 id="ssl">
+ TLS/SSL Default Configuration Changes
+</h2>
+
+<p>
+ Android 5.0 introduces changes the default TLS/SSL configuration used by apps
+ for HTTPS and other TLS/SSL traffic:
+</p>
+
+<ul>
+ <li>TLSv1.2 and TLSv1.1 protocols are now enabled,</li>
+ <li>AES-GCM (AEAD) cipher suites are now enabled,</li>
+ <li>MD5, 3DES, export, and static key ECDH cipher suites are now disabled,</li>
+ <li>Forward Secrecy cipher suites (ECDHE and DHE) are preferred.</li>
+</ul>
+
+<p>
+ These changes may lead to breakages in HTTPS or TLS/SSL connectivity in a
+ small number of cases listed below.
+</p>
+
+<p>
+ Note that the security ProviderInstaller from Google Play services already
+ offers these changes across Android platform versions back to Android 2.3.
+</p>
+
+<h3>
+ Server does not support any of the enabled ciphers suites
+</h3>
+
+<p>
+ For example, a server might support only 3DES or MD5 cipher suites. The
+ preferred fix is to improve the server’s configuration to enable stronger and
+ more modern cipher suites and protocols. Ideally, TLSv1.2 and AES-GCM should
+ be enabled, and Forward Secrecy cipher suites (ECDHE, DHE) should be enabled
+ and preferred.
+</p>
+
+<p>
+ An alternative is to modify the app to use a custom SSLSocketFactory to
+ communicate with the server. The factory should be designed to create
+ SSLSocket instances which have some of the cipher suites required by the
+ server enabled in addition to default cipher suites.
+</p>
+
+<h3>
+ App is making wrong assumptions about cipher suites used to connect to server
+</h3>
+
+<p>
+ For example, some apps contain a custom X509TrustManager that breaks because
+ it expects the authType parameter to be RSA but encounters ECDHE_RSA or
+ DHE_RSA.
+</p>
+
+<h3>
+ Server is intolerant to TLSv1.1, TLSv1.2 or new TLS extensions
+</h3>
+
+<p>
+ For example, the TLS/SSL handshake with a server is erroneously rejected or
+ stalls. The preferred fix is to upgrade the server to comply with the TLS/SSL
+ protocol. This will make the server successfully negotiate these newer
+ protocols or negotiate TLSv1 or older protocols and ignore TLS extensions it
+ does not understand. In some cases disabling TLSv1.1 and TLSv1.2 on the
+ server may work as a stopgap measure until the server software is upgraded.
+</p>
+
+<p>
+ An alternative is to modify the app to use a custom SSLSocketFactory to
+ communicate with the server. The factory should be designed to create
+ SSLSocket instances with only those protocols enabled which are correctly
+ supported by the server.
+</p> \ No newline at end of file
diff --git a/docs/html/about/versions/android-5.0.jd b/docs/html/about/versions/android-5.0.jd
index a438420..756b75f 100644
--- a/docs/html/about/versions/android-5.0.jd
+++ b/docs/html/about/versions/android-5.0.jd
@@ -15,17 +15,10 @@ sdk.platform.apiLevel=21
<ol id="toc44" class="hide-nested">
<li><a href="#ApiLevel">Update your target API level</a></li>
- <li><a href="#Behaviors">Important Behavior Changes</a>
- <ol>
- <li><a href="#ART">If you haven't tested your app against the new Android Runtime (ART)...</a></li>
- <li><a href="#BehaviorNotifications">If your app implements notifications...</a></li>
- <li><a href="#BehaviorMediaControl">If your app uses RemoteControlClient...</a></li>
-<li><a href="#BehaviorGetRecentTasks">If your app uses getRecentTasks()...</a></li>
-<li><a href="#64BitSupport">If you are using the Android Native Development Kit (NDK)...</a></li>
-<li><a href="#BindService">If your app binds to a Service...</a></li>
-<li><a href="#BehaviorWebView">If your app uses a WebView...</a></li>
- </ol>
- </li>
+
+
+
+
<li><a href="#UI">User Interface</a>
<ol>
<li><a href="#MaterialDesign">Material design support</a></li>
@@ -113,6 +106,13 @@ sdk.platform.apiLevel=21
<li><a href="{@docRoot}sdk/api_diff/preview-21/changes.html">L Developer Preview to 21 &raquo;</a> </li>
</ol>
+<h2>See Also</h2>
+<ol>
+<li><a href="{@docRoot}about/versions/android-5.0-changes.html">Android 5.0 Behavior Changes</a> </li>
+<li><a href="{@docRoot}about/versions/lollipop.html">Android Lollipop Highlights</a> </li>
+</ol>
+
+
</div>
</div>
@@ -122,12 +122,19 @@ sdk.platform.apiLevel=21
offers new features for users and app developers. This document provides an
introduction to the most notable new APIs.</p>
+<p>
+ If you have a published app, make sure to check out the <a href=
+ "{@docRoot}about/versions/android-5.0-changes.html">Android 5.0 Behavior
+ Changes</a> that you should account for in your app. These behavior changes
+ may affect your app on Android 5.0 devices, even if you are not using new APIs
+ or targeting new functionality.
+</p>
+
<p>For a high-level look at the new platform features, instead
see the
<a href="{@docRoot}about/versions/lollipop.html">Android Lollipop
highlights</a>.</p>
-
<h3 id="Start">Start developing</h3>
<p>To start building apps for Android 5.0, you must first <a href="{@docRoot}sdk/index.html">get
@@ -143,8 +150,6 @@ to download the Android 5.0 SDK Platform and System Images.</p>
">To test your apps on a real device, flash a Nexus 5 or Nexus 7 with the <br>
<a href="/preview/index.html#Start"><b>ANDROID PREVIEW SYSTEM IMAGE</b></a>.</p>
-
-
<h3 id="ApiLevel">Update your target API level</h3>
<p>To better optimize your app for devices running Android {@sdkPlatformVersion},
@@ -166,237 +171,18 @@ Different Platform Versions</a>.</p>
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">What is API
Level?</a></p>
-<h2 id="Behaviors">Important Behavior Changes</h2>
+<h3 id="Behaviors">Important behavior changes</h3>
-<p>If you have previously published an app for Android, be aware that your app
- might be affected by changes in Android 5.0.</p>
+<p>If you have previously published an app for Android, be aware that your app might be affected by changes in Android 5.0.</p>
-<h3 id="ART">If you haven't tested your app against the new Android Runtime (ART)...</h3>
-
-<p>The 4.4 release introduced a new, experimental Android runtime, ART. Under
-4.4, ART was optional, and the default runtime remained Dalvik. With Android
-5.0, ART is now the default runtime.</p>
-
-<p>For an overview of ART's new features, see
-<a href="https://source.android.com/devices/tech/dalvik/art.html">Introducing
-ART</a>. Some of the major new features are:</p>
-
-<ul>
- <li>Ahead-of-time (AOT) compilation</li>
- <li>Improved garbage collection (GC)</li>
- <li>Improved debugging support</li>
-</ul>
+<p>Please see <a href="{@docRoot}about/versions/android-5.0-changes.html">Android 5.0 Changes</a> for complete information.</p>
-<p>Most Android apps should just work without any changes under ART. However, some
-techniques that work on Dalvik do not work on ART. For information about the
-most important issues, see
-<a href="{@docRoot}guide/practices/verifying-apps-art.html">Verifying App
-Behavior on the Android Runtime (ART)</a>. Pay particular attention if:</p>
-
-<ul>
- <li>Your app uses Java Native Interface (JNI) to run C/C++ code.</li>
- <li>You use development tools that generate non-standard code (such as some
- obfuscators).</li>
- <li>You use techniques that are incompatible with compacting garbage
- collection. (ART does not currently implement compacting GC, but
- compacting GC is under development in the Android Open Source
- Project.)</li>
-</ul>
-
-<h3 id="BehaviorNotifications">If your app implements notifications...</h3>
-
-<p>Make sure your notifications take these Android 5.0 changes into account.
- To learn more about designing your notifications for Android 5.0 and higher,
- see the <a href="{@docRoot}design/patterns/notifications.html">notifications design guide</a>.
-</p>
-
-<h4 id="NotificationsMaterialDesignStyle">Material design style</h4>
-<p>Notifications are drawn with dark text atop white (or very light) backgrounds
- to match the new material design widgets. Make sure that all your
- notifications look right with the new color scheme. If your notifications
-look wrong, fix them:</p>
-
-<ul>
- <li>Use {@link android.app.Notification.Builder#setColor(int) setColor()}
- to set an accent color in a circle behind your icon image. </li>
- <li>Update or remove assets that involve color. The system ignores all
- non-alpha channels in action icons and in the main notification icon. You
- should assume that these icons will be alpha-only. The system draws
- notification icons in white and action icons in dark gray.</li>
-</ul>
-
-<h4 id="NotificationsSoundVibration">Sound and vibration</h4>
-<p>If you are currently adding sounds and vibrations to your notifications by
-using the {@link android.media.Ringtone}, {@link android.media.MediaPlayer},
-or {@link android.os.Vibrator} classes, remove this code so that
-the system can present notifications correctly in
-<em>priority</em> mode. Instead, use
-{@link android.app.Notification.Builder} methods to add sounds and
-vibration.</p>
-
-<p>Setting the device to
-{@link android.media.AudioManager#RINGER_MODE_SILENT RINGER_MODE_SILENT} causes
-the device to enter the new priority mode. The device leaves priority
-mode if you set it to
-{@link android.media.AudioManager#RINGER_MODE_NORMAL RINGER_MODE_NORMAL} or
-{@link android.media.AudioManager#RINGER_MODE_NORMAL RINGER_MODE_VIBRATE}.</p>
-
-<p>Previously, Android used {@link android.media.AudioManager#STREAM_MUSIC STREAM_MUSIC}
-as the master stream to control volume on tablet devices. In Android 5.0, the
-master volume stream for both phone and tablet devices is now unified, and
-is controlled by {@link android.media.AudioManager#STREAM_RING STREAM_RING} or
-{@link android.media.AudioManager#STREAM_NOTIFICATION STREAM_NOTIFICATION}.</p>
-
-<h4 id="NotificationsLockscreenVisibility">Lock screen visibility</h4>
-<p>By default, notifications now appear on the user's lock screen in Android 5.0.
-Users can choose to protect sensitive information from being exposed, in which
-case the system automatically redacts the text displayed by the notification. To
-customize this redacted notification, use
-{@link android.app.Notification.Builder#setPublicVersion(android.app.Notification)
- setPublicVersion()}.</p>
-<p>If the notification does not contain personal information, or if you want to
-allow media playback control on the notification, call the
-{@link android.app.Notification.Builder#setVisibility(int) setVisibility()}
-method and set the notification's visibility level to
-{@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC}.
-</p>
-
-<h4 id="NotificationsMediaPlayback">Media playback</h4>
-<p>If you are implementing notifications that present media playback
-status or transport controls, consider using the new
-{@link android.app.Notification.MediaStyle} template instead of a custom
-{@link android.widget.RemoteViews.RemoteView} object. Whichever approach you
-choose, make sure to set the notification's visibility to
-{@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC} so that
-your controls are accessible from the lock screen. Note that beginning in
-Android 5.0, the system no longer shows
-{@link android.media.RemoteControlClient} objects on the lock screen. For more
-information, see
-<a href="#BehaviorMediaControl">If your app uses RemoteControlClient</a>.</p>
-
-<h4 id="NotificationsHeadsup">Heads-up notification</h4>
-<p>Notifications may now appear in a small floating window (also called a
- heads-up notification) when the device is active (that is, the device is
- unlocked and its screen is on). These notifications appear similar to the
- compact form of your notification, except that the heads-up notification also
- shows action buttons. Users can act on, or dismiss, a heads-up notification
- without leaving the current app.</p>
-
-<p>Examples of conditions that may trigger heads-up notifications include:</p>
-
-<ul>
- <li>The user's activity is in fullscreen mode (the app uses
-{@link android.app.Notification#fullScreenIntent})</li>
- <li>The notification has high priority and uses ringtones or vibrations</li>
-</ul>
-
-<p>If your app implements notifications under any of those scenarios, make sure
-that heads-up notifications are presented correctly.</p>
-
-<h3 id="BehaviorMediaControl">If your app uses RemoteControlClient...</h3>
-<p>The {@link android.media.RemoteControlClient} class is now deprecated. Switch
- to the new {@link android.media.session.MediaSession} API as
- soon as possible.</p>
-
-<p>Lock screens in Android 5.0 do not show transport controls for
-your {@link android.media.session.MediaSession} or
-{@link android.media.RemoteControlClient}. Instead, your app can provide
-media playback control from the lock screen through a notification. This
-gives your app more control over the presentation of media buttons, while
-providing a consistent experience for users across locked and
-unlocked devices.</p>
-
-<p>Android 5.0 introduces a new
-{@link android.app.Notification.MediaStyle} template for this purpose.
-{@link android.app.Notification.MediaStyle} converts notification
-actions that you added with
-{@link android.app.Notification.Builder#addAction(int, java.lang.CharSequence,
- android.app.PendingIntent)
-Notification.Builder.addAction()} into compact buttons embedded in your app's
-media playback notifications. Pass your session token to the
-{@link android.app.Notification.MediaStyle#setMediaSession(android.media.session.MediaSession.Token)
- setSession()} method to inform the system that this notification controls an
- ongoing media session.</p>
-
-<p>Make sure to set the notification's visibility to
- {@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC}
- to mark the notification as safe to show on any lock screen (secure or
- otherwise). For more information, see
- <a href="#LockscreenNotifications">Lock screen notifications</a>.</p>
-
-<p>To display media playback controls if your app is running on the
-Android <a href="{@docRoot}tv/index.html">TV</a> or
-<a href="{@docRoot}wear/index.html">Wear</a> platform, implement the
-{@link android.media.session.MediaSession} class. You should also implement
-{@link android.media.session.MediaSession} if your app needs to receive media
-button events on Android devices.</p>
-
-<h3 id="BehaviorGetRecentTasks">If your app uses getRecentTasks()...</h3>
-
-<p>With the introduction of the new <em>concurrent documents and activities
-tasks</em> feature in Android 5.0 (see <a href="#Recents">Concurrent
-documents and activities in the recents screen</a> below),
-the {@link android.app.ActivityManager#getRecentTasks
-ActivityManager.getRecentTasks()} method is now deprecated to improve user
-privacy. For backward compatibility, this method still returns a small subset of
-its data, including the calling application’s own tasks and possibly some other
-non-sensitive tasks (such as Home). If your app is using this method to retrieve
-its own tasks, use {@link android.app.ActivityManager#getAppTasks() getAppTasks()}
-instead to retrieve that information.</p>
-
-<h3 id="64BitSupport">If you are using the Android Native Development Kit (NDK)...</h3>
-
-<p>Android 5.0 introduces support for 64-bit systems. The 64-bit enhancement
- increases address space and improves performance, while still supporting
- existing 32-bit apps fully. The 64-bit support also improves the performance of
- OpenSSL for cryptography. In addition, this release introduces new native
- media NDK APIs, as well as native OpenGL ES (GLES) 3.1 support.</p>
-
-<p>To use the 64-bit support provided in Android 5.0, download and install NDK
- Revision 10c from the
-<a href="{@docRoot}tools/sdk/ndk/index.html">Android NDK page</a>. Refer to the
-Revision 10c <a href="{@docRoot}tools/sdk/ndk/index.html#Revisions">release notes</a>
-for more information about important changes and bug fixes to the NDK.</p>
-
-<h3 id="BindService">If your app binds to a Service...</h3>
-
-<p>The
- {@link android.content.Context#bindService(android.content.Intent, android.content.ServiceConnection, int) Context.bindService()}
- method now requires an explicit {@link android.content.Intent},
-and throws an exception if given an implicit intent.
-To ensure your app is secure, use an explicit intent when starting or binding
-your {@link android.app.Service}, and do not declare intent filters for the service.</p>
-
-<h3 id="BehaviorWebView">If your app uses WebView...</h3>
-
-<p>Android 5.0 changes the default behavior for your app.</p>
-<ul>
-<li><strong>If your app targets API level 21 or higher:</strong>
- <ul>
- <li>The system
- blocks <a href="https://developer.mozilla.org/en-US/docs/Security/MixedContent"
- class="external-link">mixed content</a> and third party cookies by default. To allow mixed
- content and third party cookies, use the
- {@link android.webkit.WebSettings#setMixedContentMode(int) setMixedContentMode()}
-and {@link android.webkit.CookieManager#setAcceptThirdPartyCookies(android.webkit.WebView, boolean) setAcceptThirdPartyCookies()}
-methods respectively.</li>
- <li>The system now intelligently chooses portions of the HTML
- document to draw. This new default behavior helps to reduce memory
- footprint and increase performance. If you want to
- render the whole document at once, disable this optimization by calling
- {@link android.webkit.WebView#enableSlowWholeDocumentDraw()}.</li>
- </ul>
-</li>
-<li><strong>If your app targets API levels lower than 21:</strong> The system
- allows mixed content and third party cookies, and always renders the whole
- document at once.</li>
-</ul>
<h2 id="UI">User Interface</h2>
<h3 id="MaterialDesign">Material design support</h3>
-<p>The upcoming release adds support for Android's new <em>material design</em>
+<p>Android 5.0 adds support for Android's new <em>material design</em>
style. You can create apps with material design that are visually dynamic and
have UI element transitions that feel natural to users. This support includes:</p>
diff --git a/docs/html/design/tv/index.jd b/docs/html/design/tv/index.jd
index 483c24f..d79e279 100644
--- a/docs/html/design/tv/index.jd
+++ b/docs/html/design/tv/index.jd
@@ -1,4 +1,7 @@
-page.title=Android TV
+page.title=Designing for Android TV
+page.tags="tv", "leanback","designguidelines"
+page.metaDescription=Guidelines to help you create a great leanback experience on Android TV.
+page.image=design/tv/images/apps-games-rows.jpg
@jd:body
@@ -6,12 +9,15 @@ page.title=Android TV
experience. It's important to understand how your app is presented in the main user interface and
how your app can help users get to the content they want quickly.</p>
-<p class="note">
+<p class="caution">
<strong>Important:</strong> There are specific design requirements your app must meet to qualify
as an Android TV app on Google Play. For more information, see the requirements listed in
<a href="{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a>.
</p>
+<p class="note"><strong>Note:</strong> For information about how to publish your TV apps in Google Play,
+see <a href="/distribute/googleplay/tv.html">Distributing to Android TV</a>.</p>
+
<h2>Home Screen</h2>
<p>The Home Screen is the start of the user experience, providing search, content
diff --git a/docs/html/distribute/essentials/quality/tv.jd b/docs/html/distribute/essentials/quality/tv.jd
index b13307e..20018c3 100644
--- a/docs/html/distribute/essentials/quality/tv.jd
+++ b/docs/html/distribute/essentials/quality/tv.jd
@@ -47,11 +47,9 @@ page.image=/distribute/images/gp-tv-quality.png
qualify as an Android TV app on Google Play.
</p>
-<p class="note">
- <strong>Note:</strong> You will be able to submit TV apps to Google Play with the public release
- of Android 5.0 on November 3. Stay tuned for more information about how to submit your TV apps
- through the Google Play Developer Console.
-</p>
+<p class="note"><strong>Note:</strong> For information about how to publish your TV apps in Google Play,
+see <a href="{@docRoot}distribute/googleplay/tv.html">Distributing to Android TV</a>.</p>
+
<div class="headerLine">
diff --git a/docs/html/distribute/googleplay/edu/start.jd b/docs/html/distribute/googleplay/edu/start.jd
index 3c3a175..f4c9717 100644
--- a/docs/html/distribute/googleplay/edu/start.jd
+++ b/docs/html/distribute/googleplay/edu/start.jd
@@ -1,4 +1,4 @@
-page.title=Publish Apps
+page.title=Publish Education Apps
page.image=/distribute/images/play-education.jpg
meta.tags="education", "guidelines", "quality"
page.tags="education", "addendum"
diff --git a/docs/html/distribute/googleplay/googleplay_toc.cs b/docs/html/distribute/googleplay/googleplay_toc.cs
index 45464c7..b3aa9bf 100644
--- a/docs/html/distribute/googleplay/googleplay_toc.cs
+++ b/docs/html/distribute/googleplay/googleplay_toc.cs
@@ -18,6 +18,18 @@
</div>
</li>
<li class="nav-section">
+ <div class="nav-section empty" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/googleplay/guide.html">
+ <span class="en">Finding Success on Google Play</span>
+ </a>
+ </div>
+ </li>
+ <li class="nav-section">
+ <div class="nav-section empty" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/googleplay/tv.html">
+ <span class="en">Distributing to <span style="white-space:nowrap">Android TV</span></span>
+ </a>
+ </div>
+ </li>
+ <li class="nav-section">
<div class="nav-section-header" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/googleplay/edu/about.html">
<span class="en">Google Play for Education</span>
</a>
diff --git a/docs/html/distribute/googleplay/guide.jd b/docs/html/distribute/googleplay/guide.jd
new file mode 100644
index 0000000..8317206
--- /dev/null
+++ b/docs/html/distribute/googleplay/guide.jd
@@ -0,0 +1,71 @@
+page.title=Finding Success on Google Play
+page.metaDescription=A guide to help you find success with your app or game business on Google Play.
+meta.tags="distribute", "bestpractices"
+page.tags="google play", "business", "monetize", "engagement"
+page.image=distribute/images/play_dev_guide.png
+
+@jd:body
+
+<p>
+ We’ve created a downloadable guide to help you find success with your app or
+ game business on Google Play. In it, you’ll find features, tips, and best
+ practices to help you build an effective strategy.
+</p>
+
+<p>
+ The guide is separated into the following sections:
+</p>
+<ul>
+ <li>
+ <strong>Publishing on Google Play</strong> &mdash; using the Google Play
+ Developer Console to distribute your app to over 1 billion Android users
+ worldwide.
+ </li>
+
+ <li>
+ <strong>Quality</strong> &mdash; The fundamentals of building a great app
+ and an insight into the Google Play guidelines and policies.
+ </li>
+
+ <li>
+ <strong>Discoverability &amp; reach</strong> &mdash; Maximizing your app's
+ discoverability and reaching the widest audience possible.
+ </li>
+
+ <li>
+ <strong>Engagement &amp; retention</strong> &mdash; Converting
+ installations into active users and improving user retention.
+ </li>
+
+ <li>
+ <strong>Monetization</strong> &mdash; Monetization strategies to generate
+ ongoing, growing revenue streams.
+ </li>
+
+ <li>
+ <strong>Measurement with Google Analytics</strong> &mdash; Understanding
+ your users and improving your app experience, conversions, and marketing.
+ </li>
+
+ <li>
+ <strong>Going global</strong> &mdash; Launching your app in local markets
+ around the world.
+ </li>
+</ul>
+
+<p>
+ Download the guide by clicking the image below or <a href=
+ "http://goo.gl/DFjbrS">get it on Google Play</a>.
+</p>
+
+<p>
+ We’ll release the guide in more languages in the coming months. Check back to
+ this website regularly as we post information on new features and best
+ practices to help you distribute and monetize your app.
+</p>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:play_dev_guide"
+ data-cardSizes="9x6"
+ data-maxResults="1">
+ </div>
+
diff --git a/docs/html/distribute/googleplay/index.jd b/docs/html/distribute/googleplay/index.jd
index a215930..20f07fa 100644
--- a/docs/html/distribute/googleplay/index.jd
+++ b/docs/html/distribute/googleplay/index.jd
@@ -21,7 +21,7 @@ nonavpage=true
data-maxResults="3">
</div>
- <h3>Google Play for Education</h3>
+ <h3>Distribute Your Apps</h3>
<div class="resource-widget resource-flow-layout landing col-16"
data-query="collection:distribute/gp/gpfelanding"
diff --git a/docs/html/distribute/googleplay/tv.jd b/docs/html/distribute/googleplay/tv.jd
new file mode 100644
index 0000000..37cbe26
--- /dev/null
+++ b/docs/html/distribute/googleplay/tv.jd
@@ -0,0 +1,320 @@
+page.title=Distributing to Android TV
+page.image=/design/tv/images/atv-home.jpg
+meta.tags="tv", "publish", "quality"
+page.tags="tv", "publish", "googleplay"
+page.metaDescription=Distribute your apps, games, and content to Android TV.
+
+@jd:body
+
+<div id="qv-wrapper"><div id="qv">
+<h2>How to Participate</h2>
+<ol>
+<li><a href="#understand_guidelines">Understand the guidelines</a></li>
+<li><a href="#develop_app">Develop a great app for TV</a></li>
+<li><a href="#test_app">Test for TV App Quality</a></li>
+<li><a href="#opt_in">Opt-in</a></li>
+<li><a href="#track_review">Track your review</a></li>
+</ol>
+
+<h2>You Should Also Read</h2>
+<ol>
+<li><a href="{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a></li>
+<li><a href="{@docRoot}distribute/essentials/quality/core.html">Core App Quality</a></li>
+</ol>
+
+</div></div>
+
+<p>
+ If you've got a great app or game, Android TV and Google Play can help you
+ bring it to users right in their living rooms. You'll be able to offer your
+ apps and games in a storefront experience that’s optimized for TV. You can
+ extend your new or existing apps for TV and then publish them using familiar
+ tools and processes in Google Play.
+</p>
+
+<p>
+ To get started, review the sections in this document to learn how to
+ distribute your TV apps to users through Google Play. Be sure to read
+ <a href="{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a>
+ for information on the usability and quality standards that your apps should
+ meet. When your app is ready, you can opt-in to publishing in the Android TV
+ storefront from the Developer Console.
+</p>
+
+<h2 id="how_to_participate">
+ How to Participate
+</h2>
+
+<p>
+ Google Play lets you put your TV apps in front of a new audience of users in
+ their living rooms. You can develop and publish using your existing Developer
+ Console account and your current distribution and pricing settings. It's easy
+ to participate — the sections below outline the process.
+</p>
+
+<div style="float:right;margin:1em 0 1.5em 2em;">
+ <img src="{@docRoot}images/gp-tv-process.png">
+</div>
+
+<h3 id="understand_guidelines">
+ 1. Understand guidelines and requirements
+</h3>
+
+<p>
+ To prepare for a successful launch on Android TV, start by reviewing the
+ guidelines for creating great app experiences on TV. See the <a href=
+ "{@docRoot}design/tv/index.html">Android TV design guidelines</a> for ideas
+ on extending your app for TV and details on design and usability.
+</p>
+
+<p>
+ As you get started designing your TV experience, make sure to read and
+ understand the quality criteria for TV apps. The Google Play experience for
+ Android TV <strong>showcases only apps that are usable on the TV</strong>
+ &mdash; your apps can participate if they meet a set of basic quality
+ criteria. See <a href="{@docRoot}distribute/essentials/quality/tv.html">TV
+ App Quality</a> for details.
+</p>
+
+<h3 id="develop_app">2. Develop a great app for TV</h3>
+
+<p>
+ A great app for TV is designed for living room use and takes advantage of the
+ capabilities of Android TV and related input accessories such as game
+ controllers, D-pads, and remotes. The app is refined to offer a polished,
+ high-quality experience on large screens and delivers a compelling feature
+ set for users.
+</p>
+
+<p>
+ As you consider your TV app, review the <a href=
+ "{@docRoot}training/tv/start/index.html">developer documentation</a> and
+ usability guidelines and plan on supporting them to the greatest extent
+ possible. Make sure to design a great leanback experience for users and build
+ it with the leanback library included in the SDK. You’ll want to optimize
+ other parts of your app for the TV use case and it's a good idea to identify
+ those early in your development process.
+</p>
+
+<p>
+ In most cases, we recommend delivering your TV experience as part of your
+ existing app for phones, tablets, and other devices, using the same package
+ name and store listing. This approach lets users upgrade to your TV experience
+ seamlessly and also lets you take advantage of the reviews and ratings you’ve
+ earned in your app for phones and tablets.
+</p>
+
+<p>
+ You can bundle your TV intents, leanback library, and TV-specific code and
+ resources as part of a single APK solution for all supported devices. If
+ necessary, you can use <a href=
+ "{@docRoot}google/play/publishing/multiple-apks.html">Multiple APK
+ Support</a> to deliver a custom binary to Android TV devices under the same
+ package name and store listing that you use for phones and tablets.
+</p>
+
+<p>
+ Throughout design and development, it's important to have a suitable device
+ on which to prototype and test your user experience. You should acquire one
+ or more Android TV devices or emulators and set up your testing environment
+ as early as possible. The recommended hardware device for testing in the
+ Android TV environment is Nexus Player, which is <a href=
+ "http://www.google.com/intl/all/nexus/player/">available from Google Play</a>
+ and other stores, and you should also acquire a game controller and other TV
+ input devices.
+</p>
+
+<h3 id="test_app">3. Test for TV App Quality</h3>
+
+<p>
+ Your TV apps should be designed to perform well, look great on Android TV,
+ and offer the best user experience possible. Google Play showcases
+ high-quality apps for easy discovery by users in Google Play. Here’s how you
+ can participate and deliver an Android TV app that users will enjoy.
+</p>
+
+<ul>
+ <li>Meet Core App Quality guidelines
+ <ul>
+ <li>Follow <a href="{@docRoot}design/index.html">Android Design
+ guidelines</a>. Pay special attention to using <a href=
+ "http://www.google.com/design/spec/material-design/introduction.html">material
+ design</a> in your app.
+ </li>
+
+ <li>Test your apps against the <a href=
+ "{@docRoot}distribute/essentials/quality/core.html">Core App Quality
+ guidelines</a>.
+ </li>
+ </ul>
+ </li>
+ <li>Meet <a href="{@docRoot}distribute/essentials/quality/tv.html">TV App
+ Quality</a> guidelines
+ <ul>
+ <li>Follow our best practices for <a href="{@docRoot}training/tv/index.html">
+ TV app development</a></li>
+ <li>Make sure your app meets all of the <a href=
+ "{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a> criteria</li>
+ </ul>
+ </li>
+ <li>Strive for simplicity and highest usability</li>
+</ul>
+
+<h3 id="opt_in">4. Opt-in to Android TV and publish</h3>
+
+<p>
+ When you've built your release-ready APK and tested to ensure that it meets
+ all of the <a href="{@docRoot}distribute/essentials/quality/tv.html">TV App
+ Quality</a> guidelines, upload it to the Developer Console. Update your store
+ listing with TV screenshots and TV banner, and set distribution options as
+ needed. If you aren't familiar with how to prepare for launch on Google Play,
+ see the <a href=
+ "{@docRoot}distribute/googleplay/publish/preparing.html">Launch
+ Checklist.</a>
+</p>
+
+<p>
+ Before you can publish to Android TV users, you need to opt-in to Android
+ TV from the <strong>Pricing and Distribution</strong> section of the
+ Developer Console. Opt-in means that you want your app to be made available
+ to Android TV users through Google Play, and that
+ your app meets <a href="{@docRoot}distribute/essentials/quality/tv.html">TV
+ App Quality</a> guidelines.
+</p>
+
+<p>
+ You can opt-in only if your app meets two preliminary quality
+ criteria that are automatically checked on APK upload:
+</p>
+
+<ul>
+ <li>Your app manifest must include an intent type of <a href=
+ "{@docRoot}reference/android/content/Intent.html#ACTION_MAIN"><code>ACTION_MAIN</code></a>
+ with category <a href=
+ "{@docRoot}reference/android/content/Intent.html#CATEGORY_LEANBACK_LAUNCHER">
+ <code>CATEGORY_LEANBACK_LAUNCHER</code></a>. Learn more <a href=
+ "{@docRoot}training/tv/start/start.html#tv-activity">here</a>.
+ </li>
+
+ <li>Your app must declare that it does not require a touchscreen. The
+ manifest must declare the <code>android.hardware.touchscreen</code> hardware
+ with <code>android:required="false”</code>. Learn more <a href=
+ "{@docRoot}training/tv/start/hardware.html#declare-hardware-requirements">here</a>.
+ </li>
+</ul>
+
+<p>
+ If your app meets the preliminary criteria, you’ll see an opt-in checkbox for
+ Android TV, as shown below. If the opt-in checkbox is not enabled, review
+ your APK to ensure it meets the preliminary criteria.
+</p>
+
+<p>
+ After you opt-in and save the changes, you can publish your app as usual.
+ Before making the app available to Android TV users, Google Play submits
+ your app for review against the <a href=
+ "{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a> criteria
+ and notifies you of the result. See the next section for details on how to
+ track the approval status of your app.
+</p>
+
+<p>
+ If your app meet <a href="{@docRoot}distribute/essentials/quality/tv.html">TV
+ App Quality</a> criteria, Google Play makes that app available to Android TV
+ users. Your app is alsoeligible for higher-visibility featuring in app
+ collections and promotions. To let users everywhere know that your app is
+ designed for Android TV, Google Play decorates the app’s store listing with a
+ TV badge.
+</p>
+
+<p>
+ Note that opt-in and review do not affect the availability of your app to
+ other devices in Google Play Store &mdash; on phones and tablets, for
+ example, your app is available as soon as you publish.
+</p>
+
+<p>
+ Here are the steps to opt-in to Android TV in the Developer Console:
+</p>
+
+<ol>
+ <li>Make sure your app meets all <a href=
+ "{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a> criteria
+ </li>
+
+ <li>Add TV screenshots and banner graphic to the app’s store listing
+ </li>
+
+ <li>In the <strong>All Applications</strong> page, click the app you want to opt-in.
+ </li>
+
+ <li>Under <strong>Pricing and Distribution</strong>, scroll down to find <em>Android TV</em> and the
+ opt-in checkbox.
+ </li>
+
+ <li>Click the checkbox next to <em>Distribute your app to Android TV</em>.
+ </li>
+
+ <li>Click <strong>Save</strong> to save your changes.
+ </li>
+</ol>
+
+<div style="padding-top:1em">
+ <img style="border:2px solid #ddd;" src="{@docRoot}images/gp-tv-opt-in.png">
+ <p class="caption">
+ <strong>Opt-in for TV:</strong> Include your app in Android TV by opting-in from the
+ Developer Console.
+ </p>
+</div>
+
+<h3 id="track_review">5. Track your review and approval</h3>
+
+<p>
+ If your app meets the technical and quality criteria for Android TV, as described above,
+ your app will be available for users to enjoy on Android TV. If your app doesn’t meet
+ the criteria, you’ll receive a <strong>notification email sent to your developer account
+ address</strong>, with a summary of the areas that you need to address. When you’ve made
+ the necessary adjustments, you can upload a new version of your app to the Developer
+ Console.
+</p>
+
+<p>
+ At any time, you can check the review and approval status of your app in the
+ Developer Console, under <em>Android TV</em> in the app's <strong>Pricing and Distribution</strong>
+ page.
+</p>
+
+<p>
+ There are three approval states:
+</p>
+
+<ul>
+ <li>
+ <em>Pending</em> — Your app was sent for review and the review is not yet
+ complete.
+ </li>
+
+ <li>
+ <em>Approved</em> — Your app was reviewed and approved. The app will be
+ made available directly to Android TV users.
+ </li>
+
+ <li>
+ <em>Not approved</em> — Your app was reviewed and not approved. Check the
+ notification email for information about why the app was not approved. You
+ can address any issues and opt-in and publish again to initiate another
+ review.
+ </li>
+</ul>
+
+<p>To understand how your apps are evaluated, please see the <a href=
+"{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a> document. </p>
+
+
+ <h3>Related resources</h3>
+
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:tvlanding"
+ data-cardSizes="9x6, 6x3x2"
+ data-maxResults="6">
+ </div>
diff --git a/docs/html/distribute/images/play_dev_guide.png b/docs/html/distribute/images/play_dev_guide.png
new file mode 100644
index 0000000..5b0c0d9
--- /dev/null
+++ b/docs/html/distribute/images/play_dev_guide.png
Binary files differ
diff --git a/docs/html/distribute/images/play_dev_guide_b.jpg b/docs/html/distribute/images/play_dev_guide_b.jpg
new file mode 100644
index 0000000..15fd59f
--- /dev/null
+++ b/docs/html/distribute/images/play_dev_guide_b.jpg
Binary files differ
diff --git a/docs/html/google/auth/api-client.jd b/docs/html/google/auth/api-client.jd
index 5331d1e..a0836d1 100644
--- a/docs/html/google/auth/api-client.jd
+++ b/docs/html/google/auth/api-client.jd
@@ -15,6 +15,7 @@ startpage=true
<ol>
<li><a href="#HandlingFailures">Handle connection failures</a></li>
<li><a href="#MaintainingState">Maintain state while resolving an error</a></li>
+ <li><a href="#WearableApi">Access the Wearable API</a></li>
</ol>
</li>
<li><a href="#Communicating">Communicate with Google Services</a>
@@ -104,7 +105,17 @@ additional calls to
<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html#addScope(com.google.android.gms.common.api.Scope)"
>{@code addScope()}</a>.</p>
-<p>However, before you can begin a connection by calling <a
+<p class="caution">
+<strong>Important:</strong> To avoid client connection errors on devices that do not have the
+<a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">Android
+Wear app</a> installed, use a separate <a
+href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
+GoogleApiClient}</a> instance to access only the <a
+href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code
+Wearable}</a> API. For more information, see <a href="#WearableApi">Access the Wearable
+API</a>.</p>
+
+<p>Before you can begin a connection by calling <a
href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"
>{@code connect()}</a> on the <a
href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
@@ -408,6 +419,45 @@ consult the corresponding documentation, such as for
</p>
+<h3 id="WearableApi">Access the Wearable API</h3>
+
+<p>On devices that do not have the <a
+href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">Android
+Wear app</a> installed, connection requests that include the <a
+href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code
+Wearable}</a> API fail with the <a
+href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#API_UNAVAILABLE">
+<code>API_UNAVAILABLE</code></a> error code. If your app uses the <a
+href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code
+Wearable}</a> API in addition to other Google APIs, use a separate <a
+href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
+GoogleApiClient}</a> instance to access the <a
+href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code
+Wearable}</a> API. This approach enables you to access other Google APIs on devices that are not
+paired with a wearable device.</p>
+
+<p>When you use a separate <a
+href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
+GoogleApiClient}</a> instance to access only the Wearable API, you can determine
+whether the <a
+href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">Android
+Wear app</a> is installed on the device:</p>
+
+<pre>
+// Connection failed listener method for a client that only
+// requests access to the Wearable API
+&#64;Override
+public void onConnectionFailed(ConnectionResult result) {
+ if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) {
+ // The Android Wear app is not installed
+ }
+ ...
+}
+</pre>
+
+
+
+
<h2 id="Communicating">Communicate with Google Services</h2>
diff --git a/docs/html/images/emulator-wvga800l.png b/docs/html/images/emulator-wvga800l.png
deleted file mode 100644
index c92c1b9..0000000
--- a/docs/html/images/emulator-wvga800l.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/emulator.png b/docs/html/images/emulator.png
new file mode 100644
index 0000000..96a2507
--- /dev/null
+++ b/docs/html/images/emulator.png
Binary files differ
diff --git a/docs/html/images/emulator@2x.png b/docs/html/images/emulator@2x.png
new file mode 100644
index 0000000..9b825a7
--- /dev/null
+++ b/docs/html/images/emulator@2x.png
Binary files differ
diff --git a/docs/html/images/games/game-controller-buttons_2x_crop.png b/docs/html/images/games/game-controller-buttons_2x_crop.png
new file mode 100644
index 0000000..54dc2fa
--- /dev/null
+++ b/docs/html/images/games/game-controller-buttons_2x_crop.png
Binary files differ
diff --git a/docs/html/images/gp-tv-opt-in.png b/docs/html/images/gp-tv-opt-in.png
new file mode 100644
index 0000000..a815818
--- /dev/null
+++ b/docs/html/images/gp-tv-opt-in.png
Binary files differ
diff --git a/docs/html/images/gp-tv-process.png b/docs/html/images/gp-tv-process.png
new file mode 100644
index 0000000..a530777
--- /dev/null
+++ b/docs/html/images/gp-tv-process.png
Binary files differ
diff --git a/docs/html/images/tools/as-attach.png b/docs/html/images/tools/as-attach.png
new file mode 100644
index 0000000..c572b1e
--- /dev/null
+++ b/docs/html/images/tools/as-attach.png
Binary files differ
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index 08c0090..a38b80b 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -57,9 +57,9 @@ var RESOURCE_COLLECTIONS = {
},
"distribute/gp/gpfelanding": {
"resources": [
- "distribute/googleplay/edu/about.html",
- "distribute/googleplay/edu/start.html",
- "distribute/googleplay/edu/videos.html"
+ "distribute/googleplay/guide.html",
+ "distribute/googleplay/tv.html",
+ "distribute/googleplay/edu/about.html"
]
},
"distribute/essentials": {
@@ -773,6 +773,20 @@ var RESOURCE_COLLECTIONS = {
"https://support.google.com/googleplay/answer/2651410"
]
},
+ "tvlanding": {
+ "title": "",
+ "resources": [
+ "tv/index.html",
+ "design/tv/index.html",
+ "training/tv/index.html"
+ ]
+ },
+ "play_dev_guide": {
+ "title": "",
+ "resources": [
+ "shareables/distribute/play_dev_guide_secrets_en.pdf"
+ ]
+ },
"distribute/stories/games": {
"title": "",
"resources": [
diff --git a/docs/html/jd_extras.js b/docs/html/jd_extras.js
index 89d9761..36f26e8 100644
--- a/docs/html/jd_extras.js
+++ b/docs/html/jd_extras.js
@@ -1394,5 +1394,18 @@ DISTRIBUTE_RESOURCES = DISTRIBUTE_RESOURCES.concat([
"keywords": ["stories"],
"type": "Case Study Deck",
"titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "shareables/distribute/play_dev_guide_secrets_en.pdf",
+ "timestamp": null,
+ "image": "distribute/images/play_dev_guide_b.jpg",
+ "title": "The Secrets to App Success on Google Play",
+ "summary": "A guide to useful features, tips, and best practices that will help you grow a successful app business on Google Play.",
+ "keywords": ["distribute"],
+ "type": "PDF DOWNLOAD (11MB)",
+ "titleFriendly": ""
}
]);
diff --git a/docs/html/sdk/installing/studio-debug.jd b/docs/html/sdk/installing/studio-debug.jd
index 2e3e137..b048400 100644
--- a/docs/html/sdk/installing/studio-debug.jd
+++ b/docs/html/sdk/installing/studio-debug.jd
@@ -6,7 +6,11 @@ page.title=Debugging with Android Studio
<div id="qv">
<h2>In this document</h2>
<ol>
- <li><a href="#runDebug">Run your App in Debug Mode</a></li>
+ <li><a href="#runDebug">Run your App in Debug Mode</a>
+ <ol>
+ <li><a href="#attachDebug">Attach the debugger to a running process</a></li>
+ </ol>
+ </li>
<li><a href="#systemLog">Use the System Log</a>
<ol>
<li><a href="#systemLogWrite">Write log messages in your code</a></li>
@@ -94,6 +98,22 @@ window also provides other debugging tools covered in the following sections.</p
<p class="img-caption"><strong>Figure 2.</strong> The Debug tool window in Android Studio showing
the current thread and the object tree for a variable.</p>
+<h3 id="attachDebug">Attach the debugger to a running process</h3>
+
+<p>You don't always have to restart your app to debug it. To debug an app that you're already
+running:</p>
+
+<ol>
+<li>Click <strong>Attach debugger to Android proccess</strong>
+<img src="{@docRoot}images/tools/as-attach.png" alt=""
+style="vertical-align:bottom;margin:0;height:20px"/>.</li>
+<li>In the <em>Choose Process</em> window, select the device and app you want to attach the
+debugger to.</li>
+<li>To open the <em>Debug</em> tool window, click <strong>Debug</strong>
+<img src="{@docRoot}images/tools/as-debugwindowbutton.png"
+alt="" style="vertical-align:bottom;margin:0;height:20px"/>.</li>
+</ol>
+
<h2 id="systemLog">Use the System Log</h2>
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index 6991dea..f02cdbc 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -340,7 +340,6 @@ download (or continue to use)
</td>
</tr>
</table>
-<p class="note"><strong>Note:</strong> The full SDK/NDK requires 13 GB of disk space.</p>
</div><!-- end pax -->
diff --git a/docs/html/tools/devices/emulator.jd b/docs/html/tools/devices/emulator.jd
index ea1549d..d7bb8c7 100644
--- a/docs/html/tools/devices/emulator.jd
+++ b/docs/html/tools/devices/emulator.jd
@@ -80,7 +80,9 @@ using your mouse or keyboard to generate events for your application. It also
provides a screen in which your application is displayed, together with any other
active Android applications. </p>
-<img src="{@docRoot}images/emulator-wvga800l.png" width="367" height="349" />
+<img src="{@docRoot}images/emulator@2x.png"
+srcset="{@docRoot}images/emulator.png 1x, {@docRoot}images/emulator@2x.png 2x" alt=""
+ width="367" height="330"/>
<p>To let you model and test your application more easily, the emulator utilizes
Android Virtual Device (AVD) configurations. AVDs let you define certain hardware
diff --git a/docs/html/training/articles/security-ssl.jd b/docs/html/training/articles/security-ssl.jd
index 0639fb0..7f43d9c 100644
--- a/docs/html/training/articles/security-ssl.jd
+++ b/docs/html/training/articles/security-ssl.jd
@@ -22,6 +22,7 @@ page.article=true
<li><a href="#Blacklisting">Blacklisting</a></li>
<li><a href="#Pinning">Pinning</a></li>
<li><a href="#ClientCert">Client Certificates</a></li>
+ <li><a href="#nogotofail">Nogotofail: Network Security Testing</a></li>
</ol>
@@ -511,8 +512,42 @@ See the discussion about creating a custom {@link javax.net.ssl.KeyManager} in t
+<h2 id="nogotofail">
+ Nogotofail: A Network Traffic Security Testing Tool
+</h2>
+<p>
+ Nogotofail is a tool gives you an easy way to confirm that your apps are safe
+ against known TLS/SSL vulnerabilities and misconfigurations. It's an
+ automated, powerful, and scalable tool for testing network security issues on
+ any device whose network traffic could be made to go through it. </p>
+ <p>Nogotofail is useful for three main use cases:
+</p>
+
+<ul>
+ <li>Finding bugs and vulnerabilities.
+ </li>
+
+ <li>Verifying fixes and watching for regressions.
+ </li>
+
+ <li>Understanding what applications and devices are generating what traffic.
+ </li>
+</ul>
+
+<p>
+ Nogotofail works for Android, iOS, Linux, Windows, Chrome OS, OSX, in fact
+ any device you use to connect to the Internet. There’s an easy-to-use client
+ to configure the settings and get notifications on Android and Linux, as well
+ as the attack engine itself which can be deployed as a router, VPN server, or
+ proxy.
+</p>
+
+<p>
+ You can access the tool at the <a href=
+ "https://github.com/google/nogotofail">Nogotofail open source project</a>.
+</p>
diff --git a/docs/html/training/material/animations.jd b/docs/html/training/material/animations.jd
index e8291b8..efc0ee3 100644
--- a/docs/html/training/material/animations.jd
+++ b/docs/html/training/material/animations.jd
@@ -84,12 +84,14 @@ int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the final radius for the clipping circle
-int finalRadius = myView.getWidth();
+int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
-// create and start the animator for this view
-// (the start radius is zero)
+// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
+
+// make the view visible and start the animation
+myView.setVisibility(View.VISIBLE);
anim.start();
</pre>
diff --git a/docs/html/training/tv/discovery/index.jd b/docs/html/training/tv/discovery/index.jd
index fbc8c9f..5849149 100644
--- a/docs/html/training/tv/discovery/index.jd
+++ b/docs/html/training/tv/discovery/index.jd
@@ -1,4 +1,5 @@
-page.title=Helping Users Find Content on TV
+page.title=Helping Users Find Your Content on TV
+page.tags="tv", "leanback"
startpage=true
diff --git a/docs/html/training/tv/games/index.jd b/docs/html/training/tv/games/index.jd
index 8a998e0..5276d7f 100644
--- a/docs/html/training/tv/games/index.jd
+++ b/docs/html/training/tv/games/index.jd
@@ -1,5 +1,7 @@
page.title=Building TV Games
-page.tags="controller"
+page.tags="tv", "games", "controller"
+page.image=images/games/game-controller-buttons_2x_crop.png
+page.metaDescription=How to bring your games to Android TV, including recommendations and examples.
page.article=true
@jd:body
@@ -180,7 +182,7 @@ href="{@docRoot}training/game-controllers/controller-input.html#button"
It includes a white controller on black background and a black controller on white background
(shown in figure 1), as a PNG file and an Adobe&reg; Illustrator&reg; file.</p>
-<img src="{@docRoot}images/games/game-controller-buttons_2x.png" width="700"
+<img itemprop="image" src="{@docRoot}images/games/game-controller-buttons_2x.png" width="700"
srcset="{@docRoot}images/games/game-controller-buttons_2x.png 2x,
{@docRoot}images/games/game-controller-buttons.png 1x" />
<p class="img-caption"><b>Figure 1.</b> Example controller instructions using the
diff --git a/docs/html/training/tv/index.jd b/docs/html/training/tv/index.jd
index 56667a9..d52e1e8 100644
--- a/docs/html/training/tv/index.jd
+++ b/docs/html/training/tv/index.jd
@@ -1,8 +1,11 @@
page.title=Building Apps for TV
page.trainingcourse=true
-
+page.metaDescription=Starting point for building apps and games for Android TV, with guidelines, information, and examples.
+page.image=design/tv/images/focus.png
@jd:body
-<p>These classes teach you how to build apps for TV devices.</p> \ No newline at end of file
+<p>These classes teach you how to build apps for TV devices.</p>
+
+<p class="note"><strong>Note:</strong> For details on how to publish your TV apps in Google Play, see <a href="{docRoot}distribute/googleplay/tv.html">Distributing to Android TV</a>.</p> \ No newline at end of file
diff --git a/docs/html/training/tv/playback/index.jd b/docs/html/training/tv/playback/index.jd
index 118fc6c..09c3f24 100644
--- a/docs/html/training/tv/playback/index.jd
+++ b/docs/html/training/tv/playback/index.jd
@@ -1,5 +1,5 @@
page.title=Building TV Playback Apps
-page.tags="leanback"
+page.tags="tv","leanback"
startpage=true
diff --git a/docs/html/training/tv/start/hardware.jd b/docs/html/training/tv/start/hardware.jd
index 33d396b..fc52602 100644
--- a/docs/html/training/tv/start/hardware.jd
+++ b/docs/html/training/tv/start/hardware.jd
@@ -85,27 +85,27 @@ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION)
</tr>
<tr>
<td>Touchscreen</td>
- <td>android.hardware.touchscreen</td>
+ <td>{@code android.hardware.touchscreen}</td>
</tr>
<tr>
<td>Telephony</td>
- <td>android.hardware.telephony</td>
+ <td>{@code android.hardware.telephony}</td>
</tr>
<tr>
<td>Camera</td>
- <td>android.hardware.camera</td>
+ <td>{@code android.hardware.camera}</td>
</tr>
<tr>
<td>Near Field Communications (NFC)</td>
- <td>android.hardware.nfc</td>
+ <td>{@code android.hardware.nfc}</td>
</tr>
<tr>
<td>GPS</td>
- <td>android.hardware.location.gps</td>
+ <td>{@code android.hardware.location.gps}</td>
</tr>
<tr>
<td>Microphone</td>
- <td>android.hardware.microphone</td>
+ <td>{@code android.hardware.microphone}</td>
</tr>
</table>
@@ -142,20 +142,17 @@ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION)
android:required="false"/&gt;
</pre>
-<p class="caution">
- <strong>Caution:</strong> Declaring an unavailable hardware feature as required by setting its
- value to {@code true} in your app manifest prevents your app from being installed on TV
- devices or appearing in the Android TV home screen launcher.
+<p>
+ All apps intended for use on TV devices must declare that the touch screen feature is not required
+ as described in <a href="{@docRoot}training/tv/start/start.html#no-touchscreen">Get Started with
+ TV Apps</a>. If your app normally uses one or more of the features listed above, change the
+ {@code android:required} attribute setting to {@code false} for those features in your manifest.
</p>
<p class="caution">
- <strong>Caution:</strong> Some <a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">{@code uses-permission}</a> manifest declarations <em>imply hardware use</em>, which can also
- prevent your app from being installed and used on TV devices. For example, requesting the
- {@link android.Manifest.permission#RECORD_AUDIO} permission in your app implies the
- {@code android.hardware.microphone} hardware feature requirement. In which case, you must declare
- the microphone feature as not required ({@code android:required="false"}) in your app manifest.
- For a list of permission requests that imply a hardware feature requirement, see <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#permissions-features">
- {@code uses-feature}</a> guide.
+ <strong>Caution:</strong> Declaring a hardware feature as required by setting its
+ value to {@code true} prevents your app from being installed on TV
+ devices or appearing in the Android TV home screen launcher.
</p>
<p>
@@ -172,6 +169,52 @@ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION)
</p>
+<h3 id="hardware-permissions">Declaring permissions that imply hardware features</h3>
+
+<p>
+ Some <a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">{@code uses-permission}</a>
+ manifest declarations <em>imply hardware features</em>. This behavior means that requesting some
+ permissions in your app manifest can exclude your app from from being installed and used on TV
+ devices. The following commonly requested permissions create an implicit hardware feature
+ requirement:
+</p>
+
+<table>
+ <tr>
+ <th>Permission</th>
+ <th>Implied hardware feature</th>
+ </tr>
+ <tr>
+ <td>{@link android.Manifest.permission#RECORD_AUDIO}</td>
+ <td>{@code android.hardware.microphone}</td>
+ </tr>
+ <tr>
+ <td>{@link android.Manifest.permission#CAMERA}</td>
+ <td>{@code android.hardware.camera} <em>and</em> <br>
+ {@code android.hardware.camera.autofocus}</td>
+ </tr>
+ <tr>
+ <td>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</td>
+ <td>{@code android.hardware.location} <em>and</em> <br>
+ {@code android.hardware.location.network}</td>
+ </tr>
+ <tr>
+ <td>{@link android.Manifest.permission#ACCESS_FINE_LOCATION}</td>
+ <td>{@code android.hardware.location} <em>and</em> <br>
+ {@code android.hardware.location.gps}</td>
+ </tr>
+</table>
+
+<p>
+ For a complete list of permission requests that imply a hardware feature requirement, see
+ <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#permissions-features">{@code
+ uses-feature}</a> guide. If your app requests one of the features listed above, include a
+ <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code uses-feature}</a>
+ declaration in your manifest for the implied hardware feature that indicates it is not
+ required ({@code android:required="false"}).
+</p>
+
+
<h3 id="check-features">Checking for hardware features</h2>
<p>
diff --git a/docs/html/training/tv/start/index.jd b/docs/html/training/tv/start/index.jd
index ceefea1..fb478a8 100644
--- a/docs/html/training/tv/start/index.jd
+++ b/docs/html/training/tv/start/index.jd
@@ -1,4 +1,5 @@
page.title=Building TV Apps
+page.tags="tv", "leanback"
startpage=true
@jd:body
diff --git a/docs/html/training/tv/start/start.jd b/docs/html/training/tv/start/start.jd
index 3b26abf..aab1a39 100644
--- a/docs/html/training/tv/start/start.jd
+++ b/docs/html/training/tv/start/start.jd
@@ -11,6 +11,7 @@ startpage=true
<h2>This lesson teaches you how to</h2>
<ol>
<li><a href="#dev-project">Setup a TV Project</a></li>
+ <li><a href="#tv-libraries">Add TV Support Libraries</a></li>
<li><a href="#build-it">Build TV Apps</a></li>
<li><a href="#run">Run TV Apps</a></li>
</ol>
@@ -86,17 +87,10 @@ startpage=true
<p>An application intended to run on TV devices must declare a launcher activity for TV
in its manifest using a {@link android.content.Intent#CATEGORY_LEANBACK_LAUNCHER} intent filter.
- This filter identifies your app as being enabled for TV, allowing it to be considered a TV app
- in Google Play. Declaring this intent also identifies which activity
+ This filter identifies your app as being enabled for TV, and is required for your app to be
+ considered a TV app in Google Play. Declaring this intent also identifies which activity
in your app to launch when a user selects its icon on the TV home screen.</p>
-<p class="caution">
- <strong>Caution:</strong> If you do not include the {@link android.content.Intent#CATEGORY_LEANBACK_LAUNCHER} intent filter in
- your app, it is not visible to users running the Google Play store on TV devices. Also, if your
- app does not have this filter when you load it onto a TV device using developer tools, the app
- does not appear in the TV user interface.
-</p>
-
<p>The following code snippet shows how to include this intent filter in your manifest:</p>
<pre>
@@ -132,6 +126,14 @@ startpage=true
launch on a TV device.
</p>
+<p class="caution">
+ <strong>Caution:</strong> If you do not include the
+ {@link android.content.Intent#CATEGORY_LEANBACK_LAUNCHER} intent filter in
+ your app, it is not visible to users running the Google Play store on TV devices. Also, if your
+ app does not have this filter when you load it onto a TV device using developer tools, the app
+ does not appear in the TV user interface.
+</p>
+
<p>
If you are modifying an existing app for use on TV, your app should not use the same
activity layout for TV that it does for phones and tablets. The user interface of your TV app (or
@@ -142,6 +144,31 @@ startpage=true
"{@docRoot}training/tv/start/layouts.html">Building TV Layouts</a>.
</p>
+
+<h3 id="no-touchscreen">Declare touchscreen not required</h3>
+
+<p>
+ Applications that are intended to run on TV devices do not rely on touch screens for input. In
+ order to make this clear, the manifest of your TV app must declare that a the {@code
+ android.hardware.touchscreen} feature is not required. This setting identifies your app as being
+ able to work on a TV device, and is required for your app to be considered a TV app in Google
+ Play. The following code example shows how to include this manifest declaration:
+</p>
+
+<pre>
+&lt;manifest&gt;
+ <strong>&lt;uses-feature android:name="android.hardware.touchscreen"
+ android:required="false" /&gt;</strong>
+ ...
+&lt;/manifest&gt;
+</pre>
+
+<p class="caution">
+ <strong>Caution:</strong> You must declare that a touch screen is not required in your app
+ manifest, as shown this example code, or your app cannot appear in the Google Play store on TV
+ devices.
+</p>
+
<h3 id="banner">Provide a home screen banner</h3>
<p>
@@ -152,9 +179,10 @@ startpage=true
<pre>
&lt;application
- . . .
+ ...
android:banner="&#64;drawable/banner" &gt;
- . . .
+
+ ...
&lt;/application&gt;
</pre>
@@ -171,7 +199,7 @@ startpage=true
design guide.
</p>
-<h3 id="tv-libraries">Add TV support libraries</h3>
+<h2 id="tv-libraries">Add TV Support Libraries</h3>
<p>
The Android SDK includes support libraries that are intended for use with TV apps. These
diff --git a/docs/html/training/tv/tif/index.jd b/docs/html/training/tv/tif/index.jd
index 4746e42..cde8ba7 100644
--- a/docs/html/training/tv/tif/index.jd
+++ b/docs/html/training/tv/tif/index.jd
@@ -1,5 +1,5 @@
page.title=Building Live TV Apps
-page.tags=tif
+page.tags="tv", "tif"
page.article=true
@jd:body
diff --git a/docs/html/training/wearables/apps/bt-debugging.jd b/docs/html/training/wearables/apps/bt-debugging.jd
index 8d09c43..98cf804 100644
--- a/docs/html/training/wearables/apps/bt-debugging.jd
+++ b/docs/html/training/wearables/apps/bt-debugging.jd
@@ -58,7 +58,8 @@ Target: connected
</li>
<li>Connect the handheld to your machine over USB and run:
<pre>
-adb forward tcp:4444 localabstract:/adb-hub; adb connect localhost:4444
+adb forward tcp:4444 localabstract:/adb-hub
+adb connect localhost:4444
</pre>
<p class="note"><b>Note</b>: You can use any available port that you have access to.</p>
diff --git a/docs/html/training/wearables/data-layer/accessing.jd b/docs/html/training/wearables/data-layer/accessing.jd
index 896a698..bffd4c8 100644
--- a/docs/html/training/wearables/data-layer/accessing.jd
+++ b/docs/html/training/wearables/data-layer/accessing.jd
@@ -37,7 +37,7 @@ for more information about creating a <a href="{@docRoot}reference/com/google/an
implementing its callbacks, and handling error cases.</p>
<pre style="clear:right">
-GoogleApiClient mGoogleAppiClient = new GoogleApiClient.Builder(this)
+GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(new ConnectionCallbacks() {
&#64;Override
public void onConnected(Bundle connectionHint) {
@@ -55,13 +55,24 @@ GoogleApiClient mGoogleAppiClient = new GoogleApiClient.Builder(this)
Log.d(TAG, "onConnectionFailed: " + result);
}
})
+ // Request access only to the Wearable API
.addApi(Wearable.API)
.build();
</pre>
+<p class="caution">
+<strong>Important:</strong> To avoid client connection errors on devices that do not have the
+<a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">Android
+Wear app</a> installed, use a separate <a
+href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
+GoogleApiClient}</a> instance to access only the <a
+href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code
+Wearable}</a> API. For more information, see <a
+href="{@docRoot}google/auth/api-client.html#WearableApi">Access the Wearable API</a>.</p>
+
<p>Before you use the data layer API, start a connection on your client by calling the
<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()">connect()</a>
method, as described in
<a href="{@docRoot}google/auth/api-client.html#Starting">Accessing Google Play services APIs</a>.
When the system invokes the <code>onConnected()</code> callback for your client, you're ready
-to use the data layer API.</p> \ No newline at end of file
+to use the data layer API.</p>
diff --git a/docs/html/tv/index.jd b/docs/html/tv/index.jd
index 71e177b..e4d7f7a 100644
--- a/docs/html/tv/index.jd
+++ b/docs/html/tv/index.jd
@@ -1,5 +1,9 @@
-page.title=Android TV
+page.title=About Android TV
+page.type=about
+page.image=tv/images/hero.jpg
page.viewport_width=970
+page.tags="tv", "leanback"
+page.metaDescription=Bring your apps, games, and content to the biggest screen in the house.
fullpage=true
no_footer_links=true
page.type=about
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 1458238..94c7026 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -943,7 +943,11 @@ public class GradientDrawable extends Drawable {
float radius = st.mGradientRadius;
if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION) {
- radius *= Math.min(st.mWidth, st.mHeight);
+ // Fall back to parent width or height if intrinsic
+ // size is not specified.
+ final float width = st.mWidth >= 0 ? st.mWidth : r.width();
+ final float height = st.mHeight >= 0 ? st.mHeight : r.height();
+ radius *= Math.min(width, height);
} else if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION_PARENT) {
radius *= Math.min(r.width(), r.height());
}
@@ -954,9 +958,9 @@ public class GradientDrawable extends Drawable {
mGradientRadius = radius;
- if (radius == 0) {
- // We can't have a shader with zero radius, so let's
- // have a very, very small radius.
+ if (radius <= 0) {
+ // We can't have a shader with non-positive radius, so
+ // let's have a very, very small radius.
radius = 0.001f;
}
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 85e442d..6b84494 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -36,6 +36,17 @@
namespace android {
+/**
+ * In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
+ * casting on raw data and expect char16_t to be exactly 16 bits.
+ */
+#if __cplusplus >= 201103L
+struct __assertChar16Size {
+ static_assert(sizeof(char16_t) == sizeof(uint16_t), "char16_t is not 16 bits");
+ static_assert(alignof(char16_t) == alignof(uint16_t), "char16_t is not 16-bit aligned");
+};
+#endif
+
/** ********************************************************************
* PNG Extensions
*
@@ -702,25 +713,25 @@ public:
// These are available for all nodes:
int32_t getCommentID() const;
- const uint16_t* getComment(size_t* outLen) const;
+ const char16_t* getComment(size_t* outLen) const;
uint32_t getLineNumber() const;
// This is available for TEXT:
int32_t getTextID() const;
- const uint16_t* getText(size_t* outLen) const;
+ const char16_t* getText(size_t* outLen) const;
ssize_t getTextValue(Res_value* outValue) const;
// These are available for START_NAMESPACE and END_NAMESPACE:
int32_t getNamespacePrefixID() const;
- const uint16_t* getNamespacePrefix(size_t* outLen) const;
+ const char16_t* getNamespacePrefix(size_t* outLen) const;
int32_t getNamespaceUriID() const;
- const uint16_t* getNamespaceUri(size_t* outLen) const;
+ const char16_t* getNamespaceUri(size_t* outLen) const;
// These are available for START_TAG and END_TAG:
int32_t getElementNamespaceID() const;
- const uint16_t* getElementNamespace(size_t* outLen) const;
+ const char16_t* getElementNamespace(size_t* outLen) const;
int32_t getElementNameID() const;
- const uint16_t* getElementName(size_t* outLen) const;
+ const char16_t* getElementName(size_t* outLen) const;
// Remaining methods are for retrieving information about attributes
// associated with a START_TAG:
@@ -729,10 +740,10 @@ public:
// Returns -1 if no namespace, -2 if idx out of range.
int32_t getAttributeNamespaceID(size_t idx) const;
- const uint16_t* getAttributeNamespace(size_t idx, size_t* outLen) const;
+ const char16_t* getAttributeNamespace(size_t idx, size_t* outLen) const;
int32_t getAttributeNameID(size_t idx) const;
- const uint16_t* getAttributeName(size_t idx, size_t* outLen) const;
+ const char16_t* getAttributeName(size_t idx, size_t* outLen) const;
uint32_t getAttributeNameResID(size_t idx) const;
// These will work only if the underlying string pool is UTF-8.
@@ -740,7 +751,7 @@ public:
const char* getAttributeName8(size_t idx, size_t* outLen) const;
int32_t getAttributeValueStringID(size_t idx) const;
- const uint16_t* getAttributeStringValue(size_t idx, size_t* outLen) const;
+ const char16_t* getAttributeStringValue(size_t idx, size_t* outLen) const;
int32_t getAttributeDataType(size_t idx) const;
int32_t getAttributeData(size_t idx) const;
@@ -845,7 +856,7 @@ struct ResTable_package
uint32_t id;
// Actual name of this package, \0-terminated.
- char16_t name[128];
+ uint16_t name[128];
// Offset to a ResStringPool_header defining the resource
// type symbol table. If zero, this package is inheriting from
@@ -1450,7 +1461,7 @@ struct ResTable_lib_entry
uint32_t packageId;
// The package name of the shared library. \0 terminated.
- char16_t packageName[128];
+ uint16_t packageName[128];
};
/**
@@ -1681,7 +1692,7 @@ public:
size_t defPackageLen = 0,
uint32_t* outTypeSpecFlags = NULL) const;
- static bool expandResourceRef(const uint16_t* refStr, size_t refLen,
+ static bool expandResourceRef(const char16_t* refStr, size_t refLen,
String16* outPackage,
String16* outType,
String16* outName,
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
index dbee7ed..20d5470 100644
--- a/libs/androidfw/Android.mk
+++ b/libs/androidfw/Android.mk
@@ -14,7 +14,7 @@
LOCAL_PATH:= $(call my-dir)
-# libandroidfw is partially built for the host (used by obbtool and others)
+# libandroidfw is partially built for the host (used by obbtool, aapt, and others)
# These files are common to host and target builds.
commonSources := \
@@ -35,26 +35,17 @@ deviceSources := \
BackupHelpers.cpp \
CursorWindow.cpp
-hostSources := \
- $(commonSources)
+hostSources := $(commonSources)
# For the host
# =====================================================
-
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= $(hostSources)
-
LOCAL_MODULE:= libandroidfw
-
LOCAL_MODULE_TAGS := optional
-
LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
-
-LOCAL_C_INCLUDES := \
- external/zlib
-
-LOCAL_STATIC_LIBRARIES := liblog libziparchive-host libutils
+LOCAL_SRC_FILES:= $(hostSources)
+LOCAL_C_INCLUDES := external/zlib
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -64,8 +55,13 @@ include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
+LOCAL_MODULE:= libandroidfw
+LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES:= $(deviceSources)
-
+LOCAL_C_INCLUDES := \
+ external/zlib \
+ system/core/include
+LOCAL_STATIC_LIBRARIES := libziparchive
LOCAL_SHARED_LIBRARIES := \
libbinder \
liblog \
@@ -73,16 +69,6 @@ LOCAL_SHARED_LIBRARIES := \
libutils \
libz
-LOCAL_STATIC_LIBRARIES := libziparchive
-
-LOCAL_C_INCLUDES := \
- external/zlib \
- system/core/include
-
-LOCAL_MODULE:= libandroidfw
-
-LOCAL_MODULE_TAGS := optional
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 3bbca1a..3cf1021 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -87,11 +87,11 @@ inline static T max(T a, T b) {
// range checked; guaranteed to NUL-terminate within the stated number of available slots
// NOTE: if this truncates the dst string due to running out of space, no attempt is
// made to avoid splitting surrogate pairs.
-static void strcpy16_dtoh(uint16_t* dst, const uint16_t* src, size_t avail)
+static void strcpy16_dtoh(char16_t* dst, const uint16_t* src, size_t avail)
{
- uint16_t* last = dst + avail - 1;
+ char16_t* last = dst + avail - 1;
while (*src && (dst < last)) {
- char16_t s = dtohs(*src);
+ char16_t s = dtohs(static_cast<char16_t>(*src));
*dst++ = s;
src++;
}
@@ -501,7 +501,7 @@ status_t ResStringPool::setTo(const void* data, size_t size, bool copyData)
if (mHeader->flags&ResStringPool_header::UTF8_FLAG) {
charSize = sizeof(uint8_t);
} else {
- charSize = sizeof(char16_t);
+ charSize = sizeof(uint16_t);
}
// There should be at least space for the smallest string
@@ -547,8 +547,8 @@ status_t ResStringPool::setTo(const void* data, size_t size, bool copyData)
e[i] = dtohl(mEntries[i]);
}
if (!(mHeader->flags&ResStringPool_header::UTF8_FLAG)) {
- const char16_t* strings = (const char16_t*)mStrings;
- char16_t* s = const_cast<char16_t*>(strings);
+ const uint16_t* strings = (const uint16_t*)mStrings;
+ uint16_t* s = const_cast<uint16_t*>(strings);
for (i=0; i<mStringPoolSize; i++) {
s[i] = dtohs(strings[i]);
}
@@ -558,7 +558,7 @@ status_t ResStringPool::setTo(const void* data, size_t size, bool copyData)
if ((mHeader->flags&ResStringPool_header::UTF8_FLAG &&
((uint8_t*)mStrings)[mStringPoolSize-1] != 0) ||
(!mHeader->flags&ResStringPool_header::UTF8_FLAG &&
- ((char16_t*)mStrings)[mStringPoolSize-1] != 0)) {
+ ((uint16_t*)mStrings)[mStringPoolSize-1] != 0)) {
ALOGW("Bad string block: last string is not 0-terminated\n");
return (mError=BAD_TYPE);
}
@@ -656,7 +656,7 @@ void ResStringPool::uninit()
* add it together with the next character.
*/
static inline size_t
-decodeLength(const char16_t** str)
+decodeLength(const uint16_t** str)
{
size_t len = **str;
if ((len & 0x8000) != 0) {
@@ -689,19 +689,19 @@ decodeLength(const uint8_t** str)
return len;
}
-const uint16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const
+const char16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const
{
if (mError == NO_ERROR && idx < mHeader->stringCount) {
const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0;
- const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t));
+ const uint32_t off = mEntries[idx]/(isUTF8?sizeof(uint8_t):sizeof(uint16_t));
if (off < (mStringPoolSize-1)) {
if (!isUTF8) {
- const char16_t* strings = (char16_t*)mStrings;
- const char16_t* str = strings+off;
+ const uint16_t* strings = (uint16_t*)mStrings;
+ const uint16_t* str = strings+off;
*u16len = decodeLength(&str);
if ((uint32_t)(str+*u16len-strings) < mStringPoolSize) {
- return str;
+ return reinterpret_cast<const char16_t*>(str);
} else {
ALOGW("Bad string block: string #%d extends to %d, past end at %d\n",
(int)idx, (int)(str+*u16len-strings), (int)mStringPoolSize);
@@ -1013,7 +1013,7 @@ int32_t ResXMLParser::getCommentID() const
return mCurNode != NULL ? dtohl(mCurNode->comment.index) : -1;
}
-const uint16_t* ResXMLParser::getComment(size_t* outLen) const
+const char16_t* ResXMLParser::getComment(size_t* outLen) const
{
int32_t id = getCommentID();
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
@@ -1032,7 +1032,7 @@ int32_t ResXMLParser::getTextID() const
return -1;
}
-const uint16_t* ResXMLParser::getText(size_t* outLen) const
+const char16_t* ResXMLParser::getText(size_t* outLen) const
{
int32_t id = getTextID();
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
@@ -1055,7 +1055,7 @@ int32_t ResXMLParser::getNamespacePrefixID() const
return -1;
}
-const uint16_t* ResXMLParser::getNamespacePrefix(size_t* outLen) const
+const char16_t* ResXMLParser::getNamespacePrefix(size_t* outLen) const
{
int32_t id = getNamespacePrefixID();
//printf("prefix=%d event=%p\n", id, mEventCode);
@@ -1070,7 +1070,7 @@ int32_t ResXMLParser::getNamespaceUriID() const
return -1;
}
-const uint16_t* ResXMLParser::getNamespaceUri(size_t* outLen) const
+const char16_t* ResXMLParser::getNamespaceUri(size_t* outLen) const
{
int32_t id = getNamespaceUriID();
//printf("uri=%d event=%p\n", id, mEventCode);
@@ -1088,7 +1088,7 @@ int32_t ResXMLParser::getElementNamespaceID() const
return -1;
}
-const uint16_t* ResXMLParser::getElementNamespace(size_t* outLen) const
+const char16_t* ResXMLParser::getElementNamespace(size_t* outLen) const
{
int32_t id = getElementNamespaceID();
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
@@ -1105,7 +1105,7 @@ int32_t ResXMLParser::getElementNameID() const
return -1;
}
-const uint16_t* ResXMLParser::getElementName(size_t* outLen) const
+const char16_t* ResXMLParser::getElementName(size_t* outLen) const
{
int32_t id = getElementNameID();
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
@@ -1134,7 +1134,7 @@ int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const
return -2;
}
-const uint16_t* ResXMLParser::getAttributeNamespace(size_t idx, size_t* outLen) const
+const char16_t* ResXMLParser::getAttributeNamespace(size_t idx, size_t* outLen) const
{
int32_t id = getAttributeNamespaceID(idx);
//printf("attribute namespace=%d idx=%d event=%p\n", id, idx, mEventCode);
@@ -1165,7 +1165,7 @@ int32_t ResXMLParser::getAttributeNameID(size_t idx) const
return -1;
}
-const uint16_t* ResXMLParser::getAttributeName(size_t idx, size_t* outLen) const
+const char16_t* ResXMLParser::getAttributeName(size_t idx, size_t* outLen) const
{
int32_t id = getAttributeNameID(idx);
//printf("attribute name=%d idx=%d event=%p\n", id, idx, mEventCode);
@@ -1205,7 +1205,7 @@ int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const
return -1;
}
-const uint16_t* ResXMLParser::getAttributeStringValue(size_t idx, size_t* outLen) const
+const char16_t* ResXMLParser::getAttributeStringValue(size_t idx, size_t* outLen) const
{
int32_t id = getAttributeValueStringID(idx);
//XML_NOISY(printf("getAttributeValue 0x%x=0x%x\n", idx, id));
@@ -3645,8 +3645,12 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag
Entry entry;
status_t err = getEntry(grp, t, e, &desiredConfig, &entry);
if (err != NO_ERROR) {
+ // Only log the failure when we're not running on the host as
+ // part of a tool. The caller will do its own logging.
+#ifndef STATIC_ANDROIDFW_FOR_TOOLS
ALOGW("Failure getting entry for 0x%08x (t=%d e=%d) (error %d)\n",
resID, t, e, err);
+#endif
return err;
}
@@ -4239,7 +4243,7 @@ nope:
return 0;
}
-bool ResTable::expandResourceRef(const uint16_t* refStr, size_t refLen,
+bool ResTable::expandResourceRef(const char16_t* refStr, size_t refLen,
String16* outPackage,
String16* outType,
String16* outName,
@@ -5665,8 +5669,8 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,
if (idx == 0) {
idx = mPackageGroups.size() + 1;
- char16_t tmpName[sizeof(pkg->name)/sizeof(char16_t)];
- strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(char16_t));
+ char16_t tmpName[sizeof(pkg->name)/sizeof(pkg->name[0])];
+ strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(pkg->name[0]));
group = new PackageGroup(this, String16(tmpName), id);
if (group == NULL) {
delete package;
@@ -6036,7 +6040,10 @@ status_t ResTable::createIdmap(const ResTable& overlay,
*outSize += 2 * sizeof(uint16_t);
// overlay packages are assumed to contain only one package group
- const String16 overlayPackage(overlay.mPackageGroups[0]->packages[0]->package->name);
+ const ResTable_package* overlayPackageStruct = overlay.mPackageGroups[0]->packages[0]->package;
+ char16_t tmpName[sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0])];
+ strcpy16_dtoh(tmpName, overlayPackageStruct->name, sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0]));
+ const String16 overlayPackage(tmpName);
for (size_t typeIndex = 0; typeIndex < pg->types.size(); ++typeIndex) {
const TypeList& typeList = pg->types[typeIndex];
@@ -6345,8 +6352,10 @@ void ResTable::print(bool inclValues) const
// Use a package's real ID, since the ID may have been assigned
// if this package is a shared library.
packageId = pkg->package->id;
+ char16_t tmpName[sizeof(pkg->package->name)/sizeof(pkg->package->name[0])];
+ strcpy16_dtoh(tmpName, pkg->package->name, sizeof(pkg->package->name)/sizeof(pkg->package->name[0]));
printf(" Package %d id=0x%02x name=%s\n", (int)pkgIndex,
- pkg->package->id, String8(String16(pkg->package->name)).string());
+ pkg->package->id, String8(tmpName).string());
}
for (size_t typeIndex=0; typeIndex < pg->types.size(); typeIndex++) {
diff --git a/libs/androidfw/misc.cpp b/libs/androidfw/misc.cpp
index 29686ef..ea54cc5 100644
--- a/libs/androidfw/misc.cpp
+++ b/libs/androidfw/misc.cpp
@@ -22,9 +22,9 @@
#include <androidfw/misc.h>
#include <sys/stat.h>
-#include <string.h>
+#include <cstring>
#include <errno.h>
-#include <stdio.h>
+#include <cstdio>
using namespace android;
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index b2e465c..2d7906f 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -37,7 +37,6 @@ testFiles := \
include $(CLEAR_VARS)
LOCAL_MODULE := libandroidfw_tests
-
LOCAL_SRC_FILES := $(testFiles)
LOCAL_STATIC_LIBRARIES := \
libandroidfw \
@@ -55,11 +54,9 @@ ifneq ($(SDK_ONLY),true)
include $(CLEAR_VARS)
LOCAL_MODULE := libandroidfw_tests
-
LOCAL_SRC_FILES := $(testFiles) \
BackupData_test.cpp \
ObbFile_test.cpp
-
LOCAL_SHARED_LIBRARIES := \
libandroidfw \
libcutils \
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 7aa628c..e338686 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -340,7 +340,6 @@ public:
TessellationCache tessellationCache;
TextDropShadowCache dropShadowCache;
FboCache fboCache;
- ResourceCache resourceCache;
GammaFontRenderer* fontRenderer;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 4a927cf..8953166 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -39,29 +39,28 @@ DisplayListData::~DisplayListData() {
}
void DisplayListData::cleanupResources() {
- Caches& caches = Caches::getInstance();
- caches.unregisterFunctors(functors.size());
- caches.resourceCache.lock();
+ ResourceCache& resourceCache = ResourceCache::getInstance();
+ resourceCache.lock();
for (size_t i = 0; i < bitmapResources.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i));
+ resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i));
}
for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
const SkBitmap* bitmap = ownedBitmapResources.itemAt(i);
- caches.resourceCache.decrementRefcountLocked(bitmap);
- caches.resourceCache.destructorLocked(bitmap);
+ resourceCache.decrementRefcountLocked(bitmap);
+ resourceCache.destructorLocked(bitmap);
}
for (size_t i = 0; i < patchResources.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
+ resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
}
for (size_t i = 0; i < sourcePaths.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
+ resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
}
- caches.resourceCache.unlock();
+ resourceCache.unlock();
for (size_t i = 0; i < paints.size(); i++) {
delete paints.itemAt(i);
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index c17dd09..1b1f6cc 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -21,7 +21,7 @@
#include <private/hwui/DrawGlInfo.h>
-#include "Caches.h"
+#include "ResourceCache.h"
#include "DeferredDisplayList.h"
#include "DisplayListLogBuffer.h"
#include "DisplayListOp.h"
@@ -32,7 +32,7 @@ namespace android {
namespace uirenderer {
DisplayListRenderer::DisplayListRenderer()
- : mCaches(Caches::getInstance())
+ : mResourceCache(ResourceCache::getInstance())
, mDisplayListData(NULL)
, mTranslateX(0.0f)
, mTranslateY(0.0f)
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 901e8f0..8068663 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -24,6 +24,7 @@
#include "DisplayListLogBuffer.h"
#include "RenderNode.h"
+#include "ResourceCache.h"
namespace android {
namespace uirenderer {
@@ -209,7 +210,7 @@ private:
mDisplayListData->paths.add(pathCopy);
}
if (mDisplayListData->sourcePaths.indexOf(path) < 0) {
- mCaches.resourceCache.incrementRefcount(path);
+ mResourceCache.incrementRefcount(path);
mDisplayListData->sourcePaths.add(path);
}
return pathCopy;
@@ -273,19 +274,19 @@ private:
// contents, and drawing again. The only fix would be to always copy it the first time,
// which doesn't seem worth the extra cycles for this unlikely case.
mDisplayListData->bitmapResources.add(bitmap);
- mCaches.resourceCache.incrementRefcount(bitmap);
+ mResourceCache.incrementRefcount(bitmap);
return bitmap;
}
inline const SkBitmap* refBitmapData(const SkBitmap* bitmap) {
mDisplayListData->ownedBitmapResources.add(bitmap);
- mCaches.resourceCache.incrementRefcount(bitmap);
+ mResourceCache.incrementRefcount(bitmap);
return bitmap;
}
inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
mDisplayListData->patchResources.add(patch);
- mCaches.resourceCache.incrementRefcount(patch);
+ mResourceCache.incrementRefcount(patch);
return patch;
}
@@ -293,7 +294,7 @@ private:
DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
- Caches& mCaches;
+ ResourceCache& mResourceCache;
DisplayListData* mDisplayListData;
float mTranslateX;
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 281ca02..27ef06f 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -812,7 +812,7 @@ void PathTessellator::tessellatePoints(const float* points, int count, const SkP
// determine point shape
SkPath path;
float radius = paintInfo.halfStrokeWidth;
- if (radius == 0.0f) radius = 0.25f;
+ if (radius == 0.0f) radius = 0.5f;
if (paintInfo.cap == SkPaint::kRound_Cap) {
path.addCircle(0, 0, radius);
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index cc72ae0..0dad0dc 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -141,11 +141,12 @@ GLuint Program::buildShader(const char* source, GLenum type) {
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
+ ALOGE("Error while compiling this shader:\n===\n%s\n===", source);
// Some drivers return wrong values for GL_INFO_LOG_LENGTH
// use a fixed size instead
GLchar log[512];
glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
- LOG_ALWAYS_FATAL("Error while compiling shader: %s", log);
+ LOG_ALWAYS_FATAL("Shader info log: %s", log);
return 0;
}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index c9ed9a7..13c5499 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -98,9 +98,6 @@ void RenderNode::setStagingDisplayList(DisplayListData* data) {
mNeedsDisplayListDataSync = true;
delete mStagingDisplayListData;
mStagingDisplayListData = data;
- if (mStagingDisplayListData) {
- Caches::getInstance().registerFunctors(mStagingDisplayListData->functors.size());
- }
}
/**
@@ -305,6 +302,10 @@ void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) {
// changes in isRenderable or, in the future, bounds
damageSelf(info);
deleteDisplayListData();
+ // TODO: Remove this caches stuff
+ if (mStagingDisplayListData && mStagingDisplayListData->functors.size()) {
+ Caches::getInstance().registerFunctors(mStagingDisplayListData->functors.size());
+ }
mDisplayListData = mStagingDisplayListData;
mStagingDisplayListData = NULL;
if (mDisplayListData) {
@@ -321,6 +322,9 @@ void RenderNode::deleteDisplayListData() {
for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
mDisplayListData->children()[i]->mRenderNode->decParentRefCount();
}
+ if (mDisplayListData->functors.size()) {
+ Caches::getInstance().unregisterFunctors(mDisplayListData->functors.size());
+ }
}
delete mDisplayListData;
mDisplayListData = NULL;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 329d92f..12d4928 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -21,6 +21,12 @@
#include "Caches.h"
namespace android {
+
+#ifdef USE_OPENGL_RENDERER
+using namespace uirenderer;
+ANDROID_SINGLETON_STATIC_INSTANCE(ResourceCache);
+#endif
+
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 8539d12..a922d53 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -22,6 +22,7 @@
#include <SkBitmap.h>
#include <utils/KeyedVector.h>
+#include <utils/Singleton.h>
#include <androidfw/ResourceTypes.h>
@@ -53,11 +54,14 @@ public:
ResourceType resourceType;
};
-class ANDROID_API ResourceCache {
-public:
+class ANDROID_API ResourceCache: public Singleton<ResourceCache> {
ResourceCache();
~ResourceCache();
+ friend class Singleton<ResourceCache>;
+
+public:
+
/**
* When using these two methods, make sure to only invoke the *Locked()
* variants of increment/decrementRefcount(), recyle() and destructor()
diff --git a/location/java/android/location/GpsClock.java b/location/java/android/location/GpsClock.java
index 963b604..610d268 100644
--- a/location/java/android/location/GpsClock.java
+++ b/location/java/android/location/GpsClock.java
@@ -492,6 +492,7 @@ public class GpsClock implements Parcelable {
setType(TYPE_UNKNOWN);
setTimeInNs(Long.MIN_VALUE);
resetTimeUncertaintyInNs();
+ resetFullBiasInNs();
resetBiasInNs();
resetBiasUncertaintyInNs();
resetDriftInNsPerSec();
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2f68382..29d4930 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -533,6 +533,8 @@ public class AudioService extends IAudioService.Stub {
private AudioOrientationEventListener mOrientationListener;
+ private static Long mLastDeviceConnectMsgTime = new Long(0);
+
///////////////////////////////////////////////////////////////////////////
// Construction
///////////////////////////////////////////////////////////////////////////
@@ -740,15 +742,17 @@ public class AudioService extends IAudioService.Stub {
}
private void checkAllAliasStreamVolumes() {
- int numStreamTypes = AudioSystem.getNumStreamTypes();
- for (int streamType = 0; streamType < numStreamTypes; streamType++) {
- if (streamType != mStreamVolumeAlias[streamType]) {
- mStreamStates[streamType].
+ synchronized (VolumeStreamState.class) {
+ int numStreamTypes = AudioSystem.getNumStreamTypes();
+ for (int streamType = 0; streamType < numStreamTypes; streamType++) {
+ if (streamType != mStreamVolumeAlias[streamType]) {
+ mStreamStates[streamType].
setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]);
- }
- // apply stream volume
- if (!mStreamStates[streamType].isMuted()) {
- mStreamStates[streamType].applyAllVolumes();
+ }
+ // apply stream volume
+ if (!mStreamStates[streamType].isMuted_syncVSS()) {
+ mStreamStates[streamType].applyAllVolumes();
+ }
}
}
}
@@ -1520,7 +1524,9 @@ public class AudioService extends IAudioService.Stub {
/** get stream mute state. */
public boolean isStreamMute(int streamType) {
- return mStreamStates[streamType].isMuted();
+ synchronized (VolumeStreamState.class) {
+ return mStreamStates[streamType].isMuted_syncVSS();
+ }
}
private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
@@ -1658,17 +1664,19 @@ public class AudioService extends IAudioService.Stub {
public int getStreamVolume(int streamType) {
ensureValidStreamType(streamType);
int device = getDeviceForStream(streamType);
- int index = mStreamStates[streamType].getIndex(device);
+ synchronized (VolumeStreamState.class) {
+ int index = mStreamStates[streamType].getIndex(device);
- // by convention getStreamVolume() returns 0 when a stream is muted.
- if (mStreamStates[streamType].isMuted()) {
- index = 0;
- }
- if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
- (device & mFixedVolumeDevices) != 0) {
- index = mStreamStates[streamType].getMaxIndex();
+ // by convention getStreamVolume() returns 0 when a stream is muted.
+ if (mStreamStates[streamType].isMuted_syncVSS()) {
+ index = 0;
+ }
+ if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
+ (device & mFixedVolumeDevices) != 0) {
+ index = mStreamStates[streamType].getMaxIndex();
+ }
+ return (index + 5) / 10;
}
- return (index + 5) / 10;
}
public int getMasterVolume() {
@@ -1822,7 +1830,7 @@ public class AudioService extends IAudioService.Stub {
// on voice capable devices
if (isPlatformVoice() &&
mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
- synchronized (mStreamStates[streamType]) {
+ synchronized (VolumeStreamState.class) {
Set set = mStreamStates[streamType].mIndex.entrySet();
Iterator i = set.iterator();
while (i.hasNext()) {
@@ -2321,16 +2329,15 @@ public class AudioService extends IAudioService.Stub {
continue;
}
- synchronized (streamState) {
- streamState.readSettings();
-
+ streamState.readSettings();
+ synchronized (VolumeStreamState.class) {
// unmute stream that was muted but is not affect by mute anymore
- if (streamState.isMuted() && ((!isStreamAffectedByMute(streamType) &&
+ if (streamState.isMuted_syncVSS() && ((!isStreamAffectedByMute(streamType) &&
!isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) {
int size = streamState.mDeathHandlers.size();
for (int i = 0; i < size; i++) {
streamState.mDeathHandlers.get(i).mMuteCount = 1;
- streamState.mDeathHandlers.get(i).mute(false);
+ streamState.mDeathHandlers.get(i).mute_syncVSS(false);
}
}
}
@@ -3264,8 +3271,15 @@ public class AudioService extends IAudioService.Stub {
} else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
return;
}
-
- handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay);
+ synchronized (mLastDeviceConnectMsgTime) {
+ long time = SystemClock.uptimeMillis() + delay;
+ handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
+ if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
+ msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
+ msg == MSG_SET_A2DP_SINK_CONNECTION_STATE) {
+ mLastDeviceConnectMsgTime = time;
+ }
+ }
}
boolean checkAudioSettingsPermission(String method) {
@@ -3344,6 +3358,12 @@ public class AudioService extends IAudioService.Stub {
// Inner classes
///////////////////////////////////////////////////////////////////////////
+ // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
+ // 1 mScoclient OR mSafeMediaVolumeState
+ // 2 mSetModeDeathHandlers
+ // 3 mSettingsLock
+ // 4 VolumeStreamState.class
+ // 5 mCameraSoundForced
public class VolumeStreamState {
private final int mStreamType;
@@ -3425,9 +3445,10 @@ public class AudioService extends IAudioService.Stub {
}
}
- public void applyDeviceVolume(int device) {
+ // must be called while synchronized VolumeStreamState.class
+ public void applyDeviceVolume_syncVSS(int device) {
int index;
- if (isMuted()) {
+ if (isMuted_syncVSS()) {
index = 0;
} else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
|| ((device & mFullVolumeDevices) != 0)) {
@@ -3443,7 +3464,7 @@ public class AudioService extends IAudioService.Stub {
// apply default volume first: by convention this will reset all
// devices volumes in audio policy manager to the supplied value
int index;
- if (isMuted()) {
+ if (isMuted_syncVSS()) {
index = 0;
} else {
index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
@@ -3456,7 +3477,7 @@ public class AudioService extends IAudioService.Stub {
Map.Entry entry = (Map.Entry)i.next();
int device = ((Integer)entry.getKey()).intValue();
if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
- if (isMuted()) {
+ if (isMuted_syncVSS()) {
index = 0;
} else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
mAvrcpAbsVolSupported)
@@ -3568,12 +3589,12 @@ public class AudioService extends IAudioService.Stub {
public void mute(IBinder cb, boolean state) {
synchronized (VolumeStreamState.class) {
- VolumeDeathHandler handler = getDeathHandler(cb, state);
+ VolumeDeathHandler handler = getDeathHandler_syncVSS(cb, state);
if (handler == null) {
Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
return;
}
- handler.mute(state);
+ handler.mute_syncVSS(state);
}
}
@@ -3595,7 +3616,7 @@ public class AudioService extends IAudioService.Stub {
|| (((device & mFixedVolumeDevices) != 0) && index != 0)) {
entry.setValue(mIndexMax);
}
- applyDeviceVolume(device);
+ applyDeviceVolume_syncVSS(device);
}
}
}
@@ -3619,8 +3640,8 @@ public class AudioService extends IAudioService.Stub {
mICallback = cb;
}
- // must be called while synchronized on parent VolumeStreamState
- public void mute(boolean state) {
+ // must be called while synchronized VolumeStreamState.class
+ public void mute_syncVSS(boolean state) {
boolean updateVolume = false;
if (state) {
if (mMuteCount == 0) {
@@ -3632,7 +3653,7 @@ public class AudioService extends IAudioService.Stub {
}
VolumeStreamState.this.mDeathHandlers.add(this);
// If the stream is not yet muted by any client, set level to 0
- if (!VolumeStreamState.this.isMuted()) {
+ if (!VolumeStreamState.this.isMuted_syncVSS()) {
updateVolume = true;
}
} catch (RemoteException e) {
@@ -3656,7 +3677,7 @@ public class AudioService extends IAudioService.Stub {
if (mICallback != null) {
mICallback.unlinkToDeath(this, 0);
}
- if (!VolumeStreamState.this.isMuted()) {
+ if (!VolumeStreamState.this.isMuted_syncVSS()) {
updateVolume = true;
}
}
@@ -3674,15 +3695,17 @@ public class AudioService extends IAudioService.Stub {
public void binderDied() {
Log.w(TAG, "Volume service client died for stream: "+mStreamType);
- if (mMuteCount != 0) {
- // Reset all active mute requests from this client.
- mMuteCount = 1;
- mute(false);
+ synchronized (VolumeStreamState.class) {
+ if (mMuteCount != 0) {
+ // Reset all active mute requests from this client.
+ mMuteCount = 1;
+ mute_syncVSS(false);
+ }
}
}
}
- private synchronized int muteCount() {
+ private int muteCount() {
int count = 0;
int size = mDeathHandlers.size();
for (int i = 0; i < size; i++) {
@@ -3691,12 +3714,13 @@ public class AudioService extends IAudioService.Stub {
return count;
}
- private synchronized boolean isMuted() {
+ // must be called while synchronized VolumeStreamState.class
+ private boolean isMuted_syncVSS() {
return muteCount() != 0;
}
- // only called by mute() which is already synchronized
- private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) {
+ // must be called while synchronized VolumeStreamState.class
+ private VolumeDeathHandler getDeathHandler_syncVSS(IBinder cb, boolean state) {
VolumeDeathHandler handler;
int size = mDeathHandlers.size();
for (int i = 0; i < size; i++) {
@@ -3773,25 +3797,26 @@ public class AudioService extends IAudioService.Stub {
private void setDeviceVolume(VolumeStreamState streamState, int device) {
- // Apply volume
- streamState.applyDeviceVolume(device);
-
- // Apply change to all streams using this one as alias
- int numStreamTypes = AudioSystem.getNumStreamTypes();
- for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
- if (streamType != streamState.mStreamType &&
- mStreamVolumeAlias[streamType] == streamState.mStreamType) {
- // Make sure volume is also maxed out on A2DP device for aliased stream
- // that may have a different device selected
- int streamDevice = getDeviceForStream(streamType);
- if ((device != streamDevice) && mAvrcpAbsVolSupported &&
- ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
- mStreamStates[streamType].applyDeviceVolume(device);
+ synchronized (VolumeStreamState.class) {
+ // Apply volume
+ streamState.applyDeviceVolume_syncVSS(device);
+
+ // Apply change to all streams using this one as alias
+ int numStreamTypes = AudioSystem.getNumStreamTypes();
+ for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+ if (streamType != streamState.mStreamType &&
+ mStreamVolumeAlias[streamType] == streamState.mStreamType) {
+ // Make sure volume is also maxed out on A2DP device for aliased stream
+ // that may have a different device selected
+ int streamDevice = getDeviceForStream(streamType);
+ if ((device != streamDevice) && mAvrcpAbsVolSupported &&
+ ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
+ mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
+ }
+ mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
}
- mStreamStates[streamType].applyDeviceVolume(streamDevice);
}
}
-
// Post a persist volume msg
sendMsg(mAudioHandler,
MSG_PERSIST_VOLUME,
@@ -4571,7 +4596,12 @@ public class AudioService extends IAudioService.Stub {
if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) ||
mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) ||
mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
- delay = 1000;
+ synchronized (mLastDeviceConnectMsgTime) {
+ long time = SystemClock.uptimeMillis();
+ if (mLastDeviceConnectMsgTime > time) {
+ delay = (int)(mLastDeviceConnectMsgTime - time);
+ }
+ }
}
return delay;
}
@@ -5032,41 +5062,44 @@ public class AudioService extends IAudioService.Stub {
boolean cameraSoundForced = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_camera_sound_forced);
synchronized (mSettingsLock) {
+ boolean cameraSoundForcedChanged = false;
synchronized (mCameraSoundForced) {
if (cameraSoundForced != mCameraSoundForced) {
mCameraSoundForced = cameraSoundForced;
-
- if (!isPlatformTelevision()) {
- VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
- if (cameraSoundForced) {
- s.setAllIndexesToMax();
- mRingerModeAffectedStreams &=
- ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
- } else {
- s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
- mRingerModeAffectedStreams |=
- (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
- }
- // take new state into account for streams muted by ringer mode
- setRingerModeInt(getRingerMode(), false);
+ cameraSoundForcedChanged = true;
+ }
+ }
+ if (cameraSoundForcedChanged) {
+ if (!isPlatformTelevision()) {
+ VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
+ if (cameraSoundForced) {
+ s.setAllIndexesToMax();
+ mRingerModeAffectedStreams &=
+ ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+ } else {
+ s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
+ mRingerModeAffectedStreams |=
+ (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
}
-
- sendMsg(mAudioHandler,
- MSG_SET_FORCE_USE,
- SENDMSG_QUEUE,
- AudioSystem.FOR_SYSTEM,
- cameraSoundForced ?
- AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
- null,
- 0);
-
- sendMsg(mAudioHandler,
- MSG_SET_ALL_VOLUMES,
- SENDMSG_QUEUE,
- 0,
- 0,
- mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
+ // take new state into account for streams muted by ringer mode
+ setRingerModeInt(getRingerMode(), false);
}
+
+ sendMsg(mAudioHandler,
+ MSG_SET_FORCE_USE,
+ SENDMSG_QUEUE,
+ AudioSystem.FOR_SYSTEM,
+ cameraSoundForced ?
+ AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
+ null,
+ 0);
+
+ sendMsg(mAudioHandler,
+ MSG_SET_ALL_VOLUMES,
+ SENDMSG_QUEUE,
+ 0,
+ 0,
+ mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
}
}
mVolumeController.setLayoutDirection(config.getLayoutDirection());
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 3b8cb19..7959841 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -572,6 +572,14 @@ public final class MediaDrm {
*/
public native List<byte[]> getSecureStops();
+ /**
+ * Access secure stop by secure stop ID.
+ *
+ * @param ssid - The secure stop ID provided by the license server.
+ *
+ * @hide - not part of the public API at this time
+ */
+ public native byte[] getSecureStop(byte[] ssid);
/**
* Process the SecureStop server response message ssRelease. After authenticating
@@ -581,6 +589,12 @@ public final class MediaDrm {
*/
public native void releaseSecureStops(byte[] ssRelease);
+ /**
+ * Remove all secure stops without requiring interaction with the server.
+ *
+ * @hide - not part of the public API at this time
+ */
+ public native void releaseAllSecureStops();
/**
* String property name: identifies the maker of the DRM engine plugin
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index b4e6033..924078c 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -122,6 +122,10 @@ public final class MediaMetadata implements Parcelable {
/**
* The artwork for the media as a {@link Bitmap}.
+ * <p>
+ * The artwork should be relatively small and may be scaled down by the
+ * system if it is too large. For higher resolution artwork
+ * {@link #METADATA_KEY_ART_URI} should be used instead.
*/
public static final String METADATA_KEY_ART = "android.media.metadata.ART";
@@ -129,12 +133,20 @@ public final class MediaMetadata implements Parcelable {
* The artwork for the media as a Uri formatted String. The artwork can be
* loaded using a combination of {@link ContentResolver#openInputStream} and
* {@link BitmapFactory#decodeStream}.
+ * <p>
+ * For the best results, Uris should use the content:// style and support
+ * {@link ContentResolver#EXTRA_SIZE} for retrieving scaled artwork through
+ * {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)}.
*/
public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
/**
* The artwork for the album of the media's original source as a
* {@link Bitmap}.
+ * <p>
+ * The artwork should be relatively small and may be scaled down by the
+ * system if it is too large. For higher resolution artwork
+ * {@link #METADATA_KEY_ALBUM_ART_URI} should be used instead.
*/
public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
@@ -143,6 +155,10 @@ public final class MediaMetadata implements Parcelable {
* formatted String. The artwork can be loaded using a combination of
* {@link ContentResolver#openInputStream} and
* {@link BitmapFactory#decodeStream}.
+ * <p>
+ * For the best results, Uris should use the content:// style and support
+ * {@link ContentResolver#EXTRA_SIZE} for retrieving scaled artwork through
+ * {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)}.
*/
public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
@@ -188,6 +204,10 @@ public final class MediaMetadata implements Parcelable {
* An icon or thumbnail that is suitable for display to the user. When
* displaying an icon for media described by this metadata this should be
* preferred to other fields if present. This must be a {@link Bitmap}.
+ * <p>
+ * The icon should be relatively small and may be scaled down by the system
+ * if it is too large. For higher resolution artwork
+ * {@link #METADATA_KEY_DISPLAY_ICON_URI} should be used instead.
*/
public static final String METADATA_KEY_DISPLAY_ICON
= "android.media.metadata.DISPLAY_ICON";
@@ -199,6 +219,10 @@ public final class MediaMetadata implements Parcelable {
* fields when present. The icon can be loaded using a combination of
* {@link ContentResolver#openInputStream} and
* {@link BitmapFactory#decodeStream}.
+ * <p>
+ * For the best results, Uris should use the content:// style and support
+ * {@link ContentResolver#EXTRA_SIZE} for retrieving scaled artwork through
+ * {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)}.
*/
public static final String METADATA_KEY_DISPLAY_ICON_URI
= "android.media.metadata.DISPLAY_ICON_URI";
@@ -602,6 +626,11 @@ public final class MediaMetadata implements Parcelable {
* <li>{@link #METADATA_KEY_DISPLAY_DESCRIPTION}</li>
* <li>{@link #METADATA_KEY_DISPLAY_ICON_URI}</li>
* </ul>
+ * <p>
+ * Uris for artwork should use the content:// style and support
+ * {@link ContentResolver#EXTRA_SIZE} for retrieving scaled artwork
+ * through {@link ContentResolver#openTypedAssetFileDescriptor(Uri,
+ * String, Bundle)}.
*
* @param key The key for referencing this value
* @param value The String value to store
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index e490c2b..dd6bd20 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -449,6 +449,7 @@ public final class MediaController {
}
MessageHandler holder = new MessageHandler(handler.getLooper(), cb);
mCallbacks.add(holder);
+ holder.mRegistered = true;
if (!mCbRegistered) {
try {
@@ -467,6 +468,7 @@ public final class MediaController {
if (cb == handler.mCallback) {
mCallbacks.remove(i);
success = true;
+ handler.mRegistered = false;
}
}
if (mCbRegistered && mCallbacks.size() == 0) {
@@ -956,6 +958,7 @@ public final class MediaController {
private final static class MessageHandler extends Handler {
private final MediaController.Callback mCallback;
+ private boolean mRegistered = false;
public MessageHandler(Looper looper, MediaController.Callback cb) {
super(looper, null, true);
@@ -964,6 +967,9 @@ public final class MediaController {
@Override
public void handleMessage(Message msg) {
+ if (!mRegistered) {
+ return;
+ }
switch (msg.what) {
case MSG_EVENT:
mCallback.onSessionEvent((String) msg.obj, msg.getData());
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 86da80a..973527f 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -286,7 +286,9 @@ public final class MediaSession {
if (volumeProvider == null) {
throw new IllegalArgumentException("volumeProvider may not be null!");
}
- mVolumeProvider = volumeProvider;
+ synchronized (mLock) {
+ mVolumeProvider = volumeProvider;
+ }
volumeProvider.setCallback(new VolumeProvider.Callback() {
@Override
public void onVolumeChanged(VolumeProvider volumeProvider) {
@@ -449,6 +451,27 @@ public final class MediaSession {
}
/**
+ * Set the style of rating used by this session. Apps trying to set the
+ * rating should use this style. Must be one of the following:
+ * <ul>
+ * <li>{@link Rating#RATING_NONE}</li>
+ * <li>{@link Rating#RATING_3_STARS}</li>
+ * <li>{@link Rating#RATING_4_STARS}</li>
+ * <li>{@link Rating#RATING_5_STARS}</li>
+ * <li>{@link Rating#RATING_HEART}</li>
+ * <li>{@link Rating#RATING_PERCENTAGE}</li>
+ * <li>{@link Rating#RATING_THUMB_UP_DOWN}</li>
+ * </ul>
+ */
+ public void setRatingType(int type) {
+ try {
+ mBinder.setRatingType(type);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in setRatingType.", e);
+ }
+ }
+
+ /**
* Set some extras that can be associated with the {@link MediaSession}. No assumptions should
* be made as to how a {@link MediaController} will handle these extras.
* Keys should be fully qualified (e.g. com.example.MY_EXTRA) to avoid conflicts.
@@ -470,9 +493,11 @@ public final class MediaSession {
* @hide
*/
public void notifyRemoteVolumeChanged(VolumeProvider provider) {
- if (provider == null || provider != mVolumeProvider) {
- Log.w(TAG, "Received update from stale volume provider");
- return;
+ synchronized (mLock) {
+ if (provider == null || provider != mVolumeProvider) {
+ Log.w(TAG, "Received update from stale volume provider");
+ return;
+ }
}
try {
mBinder.setCurrentVolume(provider.getCurrentVolume());
@@ -537,6 +562,14 @@ public final class MediaSession {
postToCallback(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent);
}
+ private void dispatchAdjustVolume(int direction) {
+ postToCallback(CallbackMessageHandler.MSG_ADJUST_VOLUME, direction);
+ }
+
+ private void dispatchSetVolumeTo(int volume) {
+ postToCallback(CallbackMessageHandler.MSG_SET_VOLUME, volume);
+ }
+
private void postToCallback(int what) {
postToCallback(what, null);
}
@@ -988,9 +1021,7 @@ public final class MediaSession {
public void onAdjustVolume(int direction) {
MediaSession session = mMediaSession.get();
if (session != null) {
- if (session.mVolumeProvider != null) {
- session.mVolumeProvider.onAdjustVolume(direction);
- }
+ session.dispatchAdjustVolume(direction);
}
}
@@ -998,9 +1029,7 @@ public final class MediaSession {
public void onSetVolumeTo(int value) {
MediaSession session = mMediaSession.get();
if (session != null) {
- if (session.mVolumeProvider != null) {
- session.mVolumeProvider.onSetVolumeTo(value);
- }
+ session.dispatchSetVolumeTo(value);
}
}
@@ -1117,6 +1146,8 @@ public final class MediaSession {
private static final int MSG_CUSTOM_ACTION = 13;
private static final int MSG_MEDIA_BUTTON = 14;
private static final int MSG_COMMAND = 15;
+ private static final int MSG_ADJUST_VOLUME = 16;
+ private static final int MSG_SET_VOLUME = 17;
private MediaSession.Callback mCallback;
@@ -1145,6 +1176,7 @@ public final class MediaSession {
@Override
public void handleMessage(Message msg) {
+ VolumeProvider vp;
switch (msg.what) {
case MSG_PLAY:
mCallback.onPlay();
@@ -1192,6 +1224,22 @@ public final class MediaSession {
Command cmd = (Command) msg.obj;
mCallback.onCommand(cmd.command, cmd.extras, cmd.stub);
break;
+ case MSG_ADJUST_VOLUME:
+ synchronized (mLock) {
+ vp = mVolumeProvider;
+ }
+ if (vp != null) {
+ vp.onAdjustVolume((int) msg.obj);
+ }
+ break;
+ case MSG_SET_VOLUME:
+ synchronized (mLock) {
+ vp = mVolumeProvider;
+ }
+ if (vp != null) {
+ vp.onSetVolumeTo((int) msg.obj);
+ }
+ break;
}
}
}
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 267d1ff..54d0acd 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -16,6 +16,7 @@
package android.media.session;
import android.annotation.DrawableRes;
+import android.annotation.Nullable;
import android.media.RemoteControlClient;
import android.os.Bundle;
import android.os.Parcel;
@@ -232,11 +233,12 @@ public final class PlaybackState implements Parcelable {
private final CharSequence mErrorMessage;
private final long mUpdateTime;
private final long mActiveItemId;
+ private final Bundle mExtras;
private PlaybackState(int state, long position, long updateTime, float speed,
long bufferedPosition, long transportControls,
List<PlaybackState.CustomAction> customActions, long activeItemId,
- CharSequence error) {
+ CharSequence error, Bundle extras) {
mState = state;
mPosition = position;
mSpeed = speed;
@@ -246,6 +248,7 @@ public final class PlaybackState implements Parcelable {
mCustomActions = new ArrayList<>(customActions);
mActiveItemId = activeItemId;
mErrorMessage = error;
+ mExtras = extras;
}
private PlaybackState(Parcel in) {
@@ -258,7 +261,7 @@ public final class PlaybackState implements Parcelable {
mCustomActions = in.createTypedArrayList(CustomAction.CREATOR);
mActiveItemId = in.readLong();
mErrorMessage = in.readCharSequence();
-
+ mExtras = in.readBundle();
}
@Override
@@ -293,6 +296,7 @@ public final class PlaybackState implements Parcelable {
dest.writeTypedList(mCustomActions);
dest.writeLong(mActiveItemId);
dest.writeCharSequence(mErrorMessage);
+ dest.writeBundle(mExtras);
}
/**
@@ -306,6 +310,7 @@ public final class PlaybackState implements Parcelable {
* <li> {@link PlaybackState#STATE_REWINDING}</li>
* <li> {@link PlaybackState#STATE_BUFFERING}</li>
* <li> {@link PlaybackState#STATE_ERROR}</li>
+ * </ul>
*/
public int getState() {
return mState;
@@ -394,6 +399,15 @@ public final class PlaybackState implements Parcelable {
}
/**
+ * Get any custom extras that were set on this playback state.
+ *
+ * @return The extras for this state or null.
+ */
+ public @Nullable Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
* Get the {@link PlaybackState} state for the given
* {@link RemoteControlClient} state.
*
@@ -737,6 +751,7 @@ public final class PlaybackState implements Parcelable {
private CharSequence mErrorMessage;
private long mUpdateTime;
private long mActiveItemId = MediaSession.QueueItem.UNKNOWN_ID;
+ private Bundle mExtras;
/**
* Creates an initially empty state builder.
@@ -765,6 +780,7 @@ public final class PlaybackState implements Parcelable {
mErrorMessage = from.mErrorMessage;
mUpdateTime = from.mUpdateTime;
mActiveItemId = from.mActiveItemId;
+ mExtras = from.mExtras;
}
/**
@@ -947,13 +963,25 @@ public final class PlaybackState implements Parcelable {
}
/**
- * Build and return the {@link PlaybackState} instance with these values.
+ * Set any custom extras to be included with the playback state.
+ *
+ * @param extras The extras to include.
+ * @return this
+ */
+ public Builder setExtras(Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
+ * Build and return the {@link PlaybackState} instance with these
+ * values.
*
* @return A new state instance.
*/
public PlaybackState build() {
return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferedPosition,
- mActions, mCustomActions, mActiveItemId, mErrorMessage);
+ mActions, mCustomActions, mActiveItemId, mErrorMessage, mExtras);
}
}
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 0ca5810..93cca2f 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -159,15 +159,6 @@ public abstract class TvInputService extends Service {
}
/**
- * Get the number of callbacks that are registered.
- * @hide
- */
- @VisibleForTesting
- public final int getRegisteredCallbackCount() {
- return mCallbacks.getRegisteredCallbackCount();
- }
-
- /**
* Returns a concrete implementation of {@link Session}.
* <p>
* May return {@code null} if this TV input service fails to create a session for some reason.
@@ -550,13 +541,14 @@ public abstract class TvInputService extends Service {
* @param left Left position in pixels, relative to the overlay view.
* @param top Top position in pixels, relative to the overlay view.
* @param right Right position in pixels, relative to the overlay view.
- * @param bottm Bottom position in pixels, relative to the overlay view.
+ * @param bottom Bottom position in pixels, relative to the overlay view.
* @see #onOverlayViewSizeChanged
* @hide
*/
@SystemApi
- public void layoutSurface(final int left, final int top, final int right, final int bottm) {
- if (left > right || top > bottm) {
+ public void layoutSurface(final int left, final int top, final int right,
+ final int bottom) {
+ if (left > right || top > bottom) {
throw new IllegalArgumentException("Invalid parameter");
}
executeOrPostRunnable(new Runnable() {
@@ -564,8 +556,8 @@ public abstract class TvInputService extends Service {
public void run() {
try {
if (DEBUG) Log.d(TAG, "layoutSurface (l=" + left + ", t=" + top + ", r="
- + right + ", b=" + bottm + ",)");
- mSessionCallback.onLayoutSurface(left, top, right, bottm);
+ + right + ", b=" + bottom + ",)");
+ mSessionCallback.onLayoutSurface(left, top, right, bottom);
} catch (RemoteException e) {
Log.w(TAG, "error in layoutSurface");
}
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index d50be42..0754fd4 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -101,7 +101,6 @@ public abstract class MediaBrowserService extends Service {
* be thrown.
*
* @see MediaBrowserService#onLoadChildren
- * @see MediaBrowserService#onLoadIcon
*/
public class Result<T> {
private Object mDebug;
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 0fed27e..8e07ec0 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -1003,6 +1003,27 @@ static jobject android_media_MediaDrm_getSecureStops(
return ListOfVectorsToArrayListOfByteArray(env, secureStops);
}
+static jbyteArray android_media_MediaDrm_getSecureStop(
+ JNIEnv *env, jobject thiz, jbyteArray ssid) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (drm == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "MediaDrm obj is null");
+ return NULL;
+ }
+
+ Vector<uint8_t> secureStop;
+
+ status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
+ return NULL;
+ }
+
+ return VectorToJByteArray(env, secureStop);
+}
+
static void android_media_MediaDrm_releaseSecureStops(
JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
sp<IDrm> drm = GetDrm(env, thiz);
@@ -1020,6 +1041,21 @@ static void android_media_MediaDrm_releaseSecureStops(
throwExceptionAsNecessary(env, err, "Failed to release secure stops");
}
+static void android_media_MediaDrm_releaseAllSecureStops(
+ JNIEnv *env, jobject thiz) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (drm == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "MediaDrm obj is null");
+ return;
+ }
+
+ status_t err = drm->releaseAllSecureStops();
+
+ throwExceptionAsNecessary(env, err, "Failed to release all secure stops");
+}
+
static jstring android_media_MediaDrm_getPropertyString(
JNIEnv *env, jobject thiz, jstring jname) {
sp<IDrm> drm = GetDrm(env, thiz);
@@ -1384,9 +1420,15 @@ static JNINativeMethod gMethods[] = {
{ "getSecureStops", "()Ljava/util/List;",
(void *)android_media_MediaDrm_getSecureStops },
+ { "getSecureStop", "([B)[B",
+ (void *)android_media_MediaDrm_getSecureStop },
+
{ "releaseSecureStops", "([B)V",
(void *)android_media_MediaDrm_releaseSecureStops },
+ { "releaseAllSecureStops", "()V",
+ (void *)android_media_MediaDrm_releaseAllSecureStops },
+
{ "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
(void *)android_media_MediaDrm_getPropertyString },
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index c9cefbd..c364d46 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -803,28 +803,12 @@ static jobjectArray
android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz __unused,
jint audioSession)
{
- // kDefaultNumEffects is a "reasonable" value ensuring that only one query will be enough on
- // most devices to get all active audio pre processing on a given session.
- static const uint32_t kDefaultNumEffects = 5;
-
- effect_descriptor_t *descriptors = new effect_descriptor_t[kDefaultNumEffects];
- uint32_t numEffects = kDefaultNumEffects;
+ effect_descriptor_t *descriptors = new effect_descriptor_t[AudioEffect::kMaxPreProcessing];
+ uint32_t numEffects = AudioEffect::kMaxPreProcessing;
status_t status = AudioEffect::queryDefaultPreProcessing(audioSession,
descriptors,
&numEffects);
- if ((status != NO_ERROR && status != NO_MEMORY) ||
- numEffects == 0) {
- delete[] descriptors;
- return NULL;
- }
- if (status == NO_MEMORY) {
- delete [] descriptors;
- descriptors = new effect_descriptor_t[numEffects];
- status = AudioEffect::queryDefaultPreProcessing(audioSession,
- descriptors,
- &numEffects);
- }
if (status != NO_ERROR || numEffects == 0) {
delete[] descriptors;
return NULL;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1c6dc2c..aa5819e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -518,7 +518,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
* Determine whether the device is plugged in (USB, power, or wireless).
* @return true if the device is plugged in.
*/
- boolean isPluggedIn() {
+ public boolean isPluggedIn() {
return plugged == BatteryManager.BATTERY_PLUGGED_AC
|| plugged == BatteryManager.BATTERY_PLUGGED_USB
|| plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index c650a0f..09c7165 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -21,7 +21,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import android.os.Bundle;
+import android.os.PersistableBundle;
import android.preference.PreferenceManager;
import android.service.trust.TrustAgentService;
import android.support.v4.content.LocalBroadcastManager;
@@ -90,8 +90,15 @@ public class SampleTrustAgent extends TrustAgentService
}
@Override
- public boolean onSetTrustAgentFeaturesEnabled(Bundle options) {
- Log.v(TAG, "Policy options received: " + options.getStringArrayList(KEY_FEATURES));
+ public boolean onConfigure(Configuration config) {
+ if (config != null && config.options != null) {
+ for (int i = 0; i < config.options.size(); i++) {
+ PersistableBundle options = config.options.get(i);
+ Log.v(TAG, "Policy options received: " + options.toString());
+ }
+ } else {
+ Log.w(TAG, "onConfigure() called with no options");
+ }
// TODO: Handle options
return true; // inform DPM that we support it
}
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_cross_1.xml b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_cross_1.xml
new file mode 100644
index 0000000..a49ebf8
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_cross_1.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:valueTo="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:valueTo="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_invert_colors_disable_cross_1_pathdata_interpolator" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_icon.xml b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_icon.xml
new file mode 100644
index 0000000..9cc3b8e
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_icon.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="alpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_mask.xml b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_mask.xml
new file mode 100644
index 0000000..605ef90
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_mask.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml
new file mode 100644
index 0000000..770c401
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="1.0"
+ android:valueTo="0.3"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_cross_1.xml b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_cross_1.xml
new file mode 100644
index 0000000..94f54b6
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_cross_1.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:valueTo="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:valueTo="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_invert_colors_enable_cross_1_pathdata_interpolator" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="533"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_icon.xml b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_icon.xml
new file mode 100644
index 0000000..50a1af6
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_icon.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="alpha"
+ android:valueFrom="0.54"
+ android:valueTo="0.54"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="0.54"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_mask.xml b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_mask.xml
new file mode 100644
index 0000000..9531cd9
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_mask.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_invert_colors_enable_mask_pathdata_interpolator" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml
new file mode 100644
index 0000000..387ca29
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="0.3"
+ android:valueTo="1.0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.xml
new file mode 100644
index 0000000..9add90c
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="567"
+ android:propertyName="fillAlpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="33"
+ android:propertyName="fillAlpha"
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.xml
new file mode 100644
index 0000000..9add90c
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="567"
+ android:propertyName="fillAlpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="33"
+ android:propertyName="fillAlpha"
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml
new file mode 100644
index 0000000..6c4e133
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleX"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="1"
+ android:valueTo="0.9"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleY"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:valueFrom="1"
+ android:valueTo="0.9"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="450"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="-135"
+ android:interpolator="@interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml
new file mode 100644
index 0000000..a8f5ce0
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="267"
+ android:propertyName="pathData"
+ android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="217"
+ android:propertyName="pathData"
+ android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml
new file mode 100644
index 0000000..b9bb42d
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="-45"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml
new file mode 100644
index 0000000..b8823a9
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="250"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="33"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.xml
new file mode 100644
index 0000000..b8823a9
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="250"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="33"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml
new file mode 100644
index 0000000..14c2776
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleX"
+ android:valueFrom="0.9"
+ android:valueTo="0.9"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="0.9"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleY"
+ android:valueFrom="0.9"
+ android:valueTo="0.9"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:valueFrom="0.9"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="rotation"
+ android:valueFrom="-135"
+ android:valueTo="-135"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="450"
+ android:propertyName="rotation"
+ android:valueFrom="-135"
+ android:valueTo="0"
+ android:interpolator="@interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml
new file mode 100644
index 0000000..ea8f979
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="267"
+ android:propertyName="pathData"
+ android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="217"
+ android:propertyName="pathData"
+ android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.xml
new file mode 100644
index 0000000..4e3a356
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="rotation"
+ android:valueFrom="-45"
+ android:valueTo="-45"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="rotation"
+ android:valueFrom="-45"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_bottom.xml
new file mode 100644
index 0000000..d05c4e1
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_bottom.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="600"
+ android:propertyName="fillAlpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="fillAlpha"
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_top.xml
new file mode 100644
index 0000000..d05c4e1
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_top.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="600"
+ android:propertyName="fillAlpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="fillAlpha"
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrows.xml
new file mode 100644
index 0000000..8bcbf1e
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrows.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleX"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="1"
+ android:valueTo="0.9"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleY"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:valueFrom="1"
+ android:valueTo="0.9"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="617"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="-221"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device.xml
new file mode 100644
index 0000000..79b1827
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="-135"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device_1.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device_1.xml
new file mode 100644
index 0000000..a8f5ce0
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device_1.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="267"
+ android:propertyName="pathData"
+ android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="217"
+ android:propertyName="pathData"
+ android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_bottom.xml
new file mode 100644
index 0000000..c3ae6c1
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_bottom.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="250"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_top.xml
new file mode 100644
index 0000000..c3ae6c1
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_top.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="250"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrows.xml
new file mode 100644
index 0000000..fde172a
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrows.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="0.9"
+ android:valueTo="0.9"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="0.9"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:valueFrom="0.9"
+ android:valueTo="0.9"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:valueFrom="0.9"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="rotation"
+ android:valueFrom="-221"
+ android:valueTo="-221"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="617"
+ android:propertyName="rotation"
+ android:valueFrom="-221"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device.xml
new file mode 100644
index 0000000..accf16d
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="250"
+ android:propertyName="rotation"
+ android:valueFrom="-135"
+ android:valueTo="-135"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="rotation"
+ android:valueFrom="-135"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device_1.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device_1.xml
new file mode 100644
index 0000000..15c6705
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device_1.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="250"
+ android:propertyName="pathData"
+ android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="pathData"
+ android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_cross_1.xml b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_cross_1.xml
new file mode 100644
index 0000000..553da1a
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_cross_1.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:valueTo="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:valueTo="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_signal_airplane_disable_cross_1_pathdata_interpolator" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_ic_signal_airplane.xml b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_ic_signal_airplane.xml
new file mode 100644
index 0000000..9cc3b8e
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_ic_signal_airplane.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="alpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_mask.xml b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_mask.xml
new file mode 100644
index 0000000..605ef90
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_mask.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml
new file mode 100644
index 0000000..770c401
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="1.0"
+ android:valueTo="0.3"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_cross_1.xml b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_cross_1.xml
new file mode 100644
index 0000000..87cbaec
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_cross_1.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:valueTo="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:valueTo="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_signal_airplane_enable_cross_1_pathdata_interpolator" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="533"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_ic_signal_airplane.xml b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_ic_signal_airplane.xml
new file mode 100644
index 0000000..5fdb2a0
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_ic_signal_airplane.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="alpha"
+ android:valueFrom="0.5"
+ android:valueTo="0.5"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_mask.xml b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_mask.xml
new file mode 100644
index 0000000..56e0d1c
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_mask.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_signal_airplane_enable_mask_pathdata_interpolator" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml
new file mode 100644
index 0000000..387ca29
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="0.3"
+ android:valueTo="1.0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_cross_1.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_cross_1.xml
new file mode 100644
index 0000000..aff3567
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_cross_1.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 8.34049987793,5.6930847168 c 0.0,0.0 0.274993896484,0.29997253418 0.274993896484,0.29997253418 "
+ android:valueTo="M 8.34049987793,5.6930847168 c 0.0,0.0 0.274993896484,0.29997253418 0.274993896484,0.29997253418 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 8.34049987793,5.6930847168 c 0.0,0.0 0.274993896484,0.29997253418 0.274993896484,0.29997253418 "
+ android:valueTo="M 8.34049987793,5.6930847168 c 0.0,0.0 29.7749786377,29.7999725342 29.7749786377,29.7999725342 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_ic_signal_flashlight.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_ic_signal_flashlight.xml
new file mode 100644
index 0000000..9cc3b8e
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_ic_signal_flashlight.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="alpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_mask.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_mask.xml
new file mode 100644
index 0000000..31583f2
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_mask.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-39.2849731445 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-39.2849731445 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-39.2849731445 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-39.2975769043 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml
new file mode 100644
index 0000000..770c401
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="1.0"
+ android:valueTo="0.3"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_cross_1.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_cross_1.xml
new file mode 100644
index 0000000..c923015
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_cross_1.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 8.34049987793,5.6930847168 c 0.0,0.0 29.7749786377,29.7999725342 29.7749786377,29.7999725342 "
+ android:valueTo="M 8.34049987793,5.6930847168 c 0.0,0.0 29.7749786377,29.7999725342 29.7749786377,29.7999725342 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 8.34049987793,5.6930847168 c 0.0,0.0 29.7749786377,29.7999725342 29.7749786377,29.7999725342 "
+ android:valueTo="M 8.34049987793,5.6930847168 c 0.0,0.0 0.274993896484,0.29997253418 0.274993896484,0.29997253418 "
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_signal_flashlight_enable_cross_1_pathdata_interpolator" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="533"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_ic_signal_flashlight.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_ic_signal_flashlight.xml
new file mode 100644
index 0000000..5fdb2a0
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_ic_signal_flashlight.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="alpha"
+ android:valueFrom="0.5"
+ android:valueTo="0.5"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_mask.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_mask.xml
new file mode 100644
index 0000000..650d89f
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_mask.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-39.2975769043 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-39.2975769043 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 37.8337860107,-39.2975769043 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 37.8337860107,-39.2849731445 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_signal_flashlight_enable_mask_pathdata_interpolator" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml
new file mode 100644
index 0000000..387ca29
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="0.3"
+ android:valueTo="1.0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_disable_animation_cross_1.xml b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_cross_1.xml
new file mode 100644
index 0000000..73283a8
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_cross_1.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 6.44050598145,1.9430847168 c 0.0,0.0 0.374984741211,0.399978637695 0.374984741211,0.399978637695 "
+ android:valueTo="M 6.44050598145,1.9430847168 c 0.0,0.0 0.374984741211,0.399978637695 0.374984741211,0.399978637695 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 6.44050598145,1.9430847168 c 0.0,0.0 0.374984741211,0.399978637695 0.374984741211,0.399978637695 "
+ android:valueTo="M 6.44050598145,1.9430847168 c 0.0,0.0 33.5749816895,33.4499664307 33.5749816895,33.4499664307 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_disable_animation_ic_signal_location.xml b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_ic_signal_location.xml
new file mode 100644
index 0000000..9cc3b8e
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_ic_signal_location.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="alpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_disable_animation_mask.xml b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_mask.xml
new file mode 100644
index 0000000..7ef7b5b
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_mask.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 38.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 7.3759765625,7.55284118652 7.3759765625,7.55284118652 c 0.0,0.0 -2.61698913574,2.0938873291 -2.61698913574,2.0938873291 c 0.0,0.0 -7.57595825195,-7.56428527832 -7.57595825195,-7.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 38.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 7.3759765625,7.55284118652 7.3759765625,7.55284118652 c 0.0,0.0 -2.61698913574,2.0938873291 -2.61698913574,2.0938873291 c 0.0,0.0 -7.57595825195,-7.56428527832 -7.57595825195,-7.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 38.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 7.3759765625,7.55284118652 7.3759765625,7.55284118652 c 0.0,0.0 -2.61698913574,2.0938873291 -2.61698913574,2.0938873291 c 0.0,0.0 -7.57595825195,-7.56428527832 -7.57595825195,-7.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 38.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,41.1153411865 40.9884796143,41.1153411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-41.1267852783 -41.1884460449,-41.1267852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml
new file mode 100644
index 0000000..770c401
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="1.0"
+ android:valueTo="0.3"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_enable_animation_cross_1.xml b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_cross_1.xml
new file mode 100644
index 0000000..f4fc20e
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_cross_1.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 6.44050598145,1.9430847168 c 0.0,0.0 33.5749816895,33.4499664307 33.5749816895,33.4499664307 "
+ android:valueTo="M 6.44050598145,1.9430847168 c 0.0,0.0 33.5749816895,33.4499664307 33.5749816895,33.4499664307 "
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 6.44050598145,1.9430847168 c 0.0,0.0 33.5749816895,33.4499664307 33.5749816895,33.4499664307 "
+ android:valueTo="M 6.44050598145,1.9430847168 c 0.0,0.0 0.374984741211,0.399978637695 0.374984741211,0.399978637695 "
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_signal_location_enable_cross_1_pathdata_interpolator" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="533"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_enable_animation_ic_signal_location.xml b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_ic_signal_location.xml
new file mode 100644
index 0000000..5fdb2a0
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_ic_signal_location.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="alpha"
+ android:valueFrom="0.5"
+ android:valueTo="0.5"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_enable_animation_mask.xml b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_mask.xml
new file mode 100644
index 0000000..b825eb9
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_mask.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="pathData"
+ android:valueFrom="M 38.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,41.1153411865 40.9884796143,41.1153411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-41.1267852783 -41.1884460449,-41.1267852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 38.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,41.1153411865 40.9884796143,41.1153411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-41.1267852783 -41.1884460449,-41.1267852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 38.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,41.1153411865 40.9884796143,41.1153411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-41.1267852783 -41.1884460449,-41.1267852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueTo="M 38.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 7.3759765625,7.55284118652 7.3759765625,7.55284118652 c 0.0,0.0 -2.61698913574,2.0938873291 -2.61698913574,2.0938873291 c 0.0,0.0 -7.57595825195,-7.56428527832 -7.57595825195,-7.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z"
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_signal_location_enable_mask_pathdata_interpolator" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml
new file mode 100644
index 0000000..387ca29
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="0.3"
+ android:valueTo="1.0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
new file mode 100644
index 0000000..f901e86
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
@@ -0,0 +1,56 @@
+<?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"
+ android:name="root"
+ android:alpha="1.0"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="icon"
+ android:translateX="21.9995"
+ android:translateY="25.73401" >
+ <group
+ android:name="icon_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="0"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="ink_drop"
+ android:translateY="-6.8" >
+ <path
+ android:name="outer_drop"
+ android:pathData="M 35.3000030518,15.8999938965 c 0.0,0.0 -11.3000030518,-11.3999938965 -11.3000030518,-11.3999938965 c 0,0.0 -11.3000030518,11.3999938965 -11.3000030518,11.3999938965 c -6.19999694824,6.20001220703 -6.19999694824,16.4000091553 0.0,22.6000061035 c 3.10000610352,3.10000610352 7.19999694824,4.69999694824 11.3000030518,4.69999694824 c 4.10000610352,0.0 8.19999694824,-1.59999084473 11.3000030518,-4.69999694824 c 6.30000305176,-6.30000305176 6.30000305176,-16.3999938965 0.0,-22.6000061035 Z M 24,39.1999969482 c 0,0.0 0,0.0 0,0.0 c -3.19999694824,0.0 -6.19999694824,-1.19999694824 -8.5,-3.5 c -2.30000305176,-2.29998779297 -3.5,-5.30000305176 -3.5,-8.5 c 0,-3.19999694824 1.19999694824,-6.19999694824 3.5,-8.5 c 0.0,0.0 8.5,-8.5 8.5,-8.5 c 0,0.0 0,29.0 0,29.0 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml b/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml
new file mode 100644
index 0000000..2e26d42
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_invert_colors_disable" >
+ <target
+ android:name="root"
+ android:animation="@anim/ic_invert_colors_disable_animation_root" />
+ <target
+ android:name="icon"
+ android:animation="@anim/ic_invert_colors_disable_animation_icon" />
+ <target
+ android:name="mask"
+ android:animation="@anim/ic_invert_colors_disable_animation_mask" />
+ <target
+ android:name="cross_1"
+ android:animation="@anim/ic_invert_colors_disable_animation_cross_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
new file mode 100644
index 0000000..730ecc4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
@@ -0,0 +1,57 @@
+<?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"
+ android:name="root"
+ android:alpha="0.3"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="icon"
+ android:translateX="21.9995"
+ android:translateY="25.73401"
+ android:alpha="0.54" >
+ <group
+ android:name="icon_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="1"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="ink_drop"
+ android:translateY="-6.8" >
+ <path
+ android:name="outer_drop"
+ android:pathData="M 35.3000030518,15.8999938965 c 0.0,0.0 -11.3000030518,-11.3999938965 -11.3000030518,-11.3999938965 c 0,0.0 -11.3000030518,11.3999938965 -11.3000030518,11.3999938965 c -6.19999694824,6.20001220703 -6.19999694824,16.4000091553 0.0,22.6000061035 c 3.10000610352,3.10000610352 7.19999694824,4.69999694824 11.3000030518,4.69999694824 c 4.10000610352,0.0 8.19999694824,-1.59999084473 11.3000030518,-4.69999694824 c 6.30000305176,-6.30000305176 6.30000305176,-16.3999938965 0.0,-22.6000061035 Z M 24,39.1999969482 c 0,0.0 0,0.0 0,0.0 c -3.19999694824,0.0 -6.19999694824,-1.19999694824 -8.5,-3.5 c -2.30000305176,-2.29998779297 -3.5,-5.30000305176 -3.5,-8.5 c 0,-3.19999694824 1.19999694824,-6.19999694824 3.5,-8.5 c 0.0,0.0 8.5,-8.5 8.5,-8.5 c 0,0.0 0,29.0 0,29.0 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/ic_open_animation.xml b/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml
index 83ee90b..a709efb 100644
--- a/tests/VectorDrawableTest/res/drawable/ic_open_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml
@@ -1,4 +1,6 @@
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?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.
@@ -13,17 +15,17 @@
limitations under the License.
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/ic_open" >
+ android:drawable="@drawable/ic_invert_colors_enable" >
<target
- android:name="ball_start"
- android:animation="@anim/ic_open_animation_ball_start" />
+ android:name="root"
+ android:animation="@anim/ic_invert_colors_enable_animation_root" />
<target
- android:name="path_1"
- android:animation="@anim/ic_open_animation_path_1" />
+ android:name="icon"
+ android:animation="@anim/ic_invert_colors_enable_animation_icon" />
<target
- android:name="ball_swoop"
- android:animation="@anim/ic_open_animation_ball_swoop" />
+ android:name="mask"
+ android:animation="@anim/ic_invert_colors_enable_animation_mask" />
<target
- android:name="path_1_1"
- android:animation="@anim/ic_open_animation_path_1_1" />
+ android:name="cross_1"
+ android:animation="@anim/ic_invert_colors_enable_animation_cross_1" />
</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
new file mode 100644
index 0000000..bc545ba
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
@@ -0,0 +1,62 @@
+<?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"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_screen_rotation_48px_outlines"
+ android:translateX="24"
+ android:translateY="24" >
+ <group
+ android:name="ic_screen_rotation_48px_outlines_pivot"
+ android:translateX="-24.15"
+ android:translateY="-24.25" >
+ <group
+ android:name="arrows"
+ android:translateX="24.1"
+ android:translateY="24.1" >
+ <group
+ android:name="arrows_pivot"
+ android:translateX="-24.1"
+ android:translateY="-24.1" >
+ <path
+ android:name="arrow_top"
+ android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ <path
+ android:name="arrow_bottom"
+ android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ <group
+ android:name="device"
+ android:translateX="24.14999"
+ android:translateY="24.25" >
+ <path
+ android:name="body"
+ android:pathData="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
new file mode 100644
index 0000000..400a28b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_landscape_from_auto_rotate" >
+ <target
+ android:name="arrows"
+ android:animation="@anim/ic_landscape_from_auto_rotate_animation_arrows" />
+ <target
+ android:name="arrow_top"
+ android:animation="@anim/ic_landscape_from_auto_rotate_animation_arrow_top" />
+ <target
+ android:name="arrow_bottom"
+ android:animation="@anim/ic_landscape_from_auto_rotate_animation_arrow_bottom" />
+ <target
+ android:name="device"
+ android:animation="@anim/ic_landscape_from_auto_rotate_animation_device" />
+ <target
+ android:name="body"
+ android:animation="@anim/ic_landscape_from_auto_rotate_animation_body" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
new file mode 100644
index 0000000..0bd75d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
@@ -0,0 +1,66 @@
+<?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"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_screen_rotation_48px_outlines"
+ android:translateX="24"
+ android:translateY="24" >
+ <group
+ android:name="ic_screen_rotation_48px_outlines_pivot"
+ android:translateX="-24.15"
+ android:translateY="-24.25" >
+ <group
+ android:name="arrows"
+ android:translateX="24.1"
+ android:translateY="24.1"
+ android:scaleX="0.9"
+ android:scaleY="0.9"
+ android:rotation="-135" >
+ <group
+ android:name="arrows_pivot"
+ android:translateX="-24.1"
+ android:translateY="-24.1" >
+ <path
+ android:name="arrow_top"
+ android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="0" />
+ <path
+ android:name="arrow_bottom"
+ android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="0" />
+ </group>
+ </group>
+ <group
+ android:name="device"
+ android:translateX="24.14999"
+ android:translateY="24.25"
+ android:rotation="-45" >
+ <path
+ android:name="body"
+ android:pathData="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
new file mode 100644
index 0000000..5263eb4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_landscape_to_auto_rotate" >
+ <target
+ android:name="arrows"
+ android:animation="@anim/ic_landscape_to_auto_rotate_animation_arrows" />
+ <target
+ android:name="arrow_top"
+ android:animation="@anim/ic_landscape_to_auto_rotate_animation_arrow_top" />
+ <target
+ android:name="arrow_bottom"
+ android:animation="@anim/ic_landscape_to_auto_rotate_animation_arrow_bottom" />
+ <target
+ android:name="device"
+ android:animation="@anim/ic_landscape_to_auto_rotate_animation_device" />
+ <target
+ android:name="body"
+ android:animation="@anim/ic_landscape_to_auto_rotate_animation_body" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
new file mode 100644
index 0000000..1805a8e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
@@ -0,0 +1,62 @@
+<?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"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_screen_rotation_48px_outlines"
+ android:translateX="24"
+ android:translateY="24" >
+ <group
+ android:name="ic_screen_rotation_48px_outlines_pivot"
+ android:translateX="-24.15"
+ android:translateY="-24.25" >
+ <group
+ android:name="arrows"
+ android:translateX="24.1"
+ android:translateY="24.1" >
+ <group
+ android:name="arrows_pivot"
+ android:translateX="-24.1"
+ android:translateY="-24.1" >
+ <path
+ android:name="arrow_top"
+ android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ <path
+ android:name="arrow_bottom"
+ android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ <group
+ android:name="device"
+ android:translateX="24.14999"
+ android:translateY="24.25" >
+ <path
+ android:name="device_1"
+ android:pathData="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml
new file mode 100644
index 0000000..565ef26
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_portrait_from_auto_rotate" >
+ <target
+ android:name="arrows"
+ android:animation="@anim/ic_portrait_from_auto_rotate_animation_arrows" />
+ <target
+ android:name="arrow_top"
+ android:animation="@anim/ic_portrait_from_auto_rotate_animation_arrow_top" />
+ <target
+ android:name="arrow_bottom"
+ android:animation="@anim/ic_portrait_from_auto_rotate_animation_arrow_bottom" />
+ <target
+ android:name="device"
+ android:animation="@anim/ic_portrait_from_auto_rotate_animation_device" />
+ <target
+ android:name="device_1"
+ android:animation="@anim/ic_portrait_from_auto_rotate_animation_device_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
new file mode 100644
index 0000000..feb3025
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
@@ -0,0 +1,66 @@
+<?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"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_screen_rotation_48px_outlines"
+ android:translateX="24"
+ android:translateY="24" >
+ <group
+ android:name="ic_screen_rotation_48px_outlines_pivot"
+ android:translateX="-24.15"
+ android:translateY="-24.25" >
+ <group
+ android:name="arrows"
+ android:translateX="24.1"
+ android:translateY="24.1"
+ android:scaleX="0.9"
+ android:scaleY="0.9"
+ android:rotation="-221" >
+ <group
+ android:name="arrows_pivot"
+ android:translateX="-24.1"
+ android:translateY="-24.1" >
+ <path
+ android:name="arrow_top"
+ android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="0" />
+ <path
+ android:name="arrow_bottom"
+ android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="0" />
+ </group>
+ </group>
+ <group
+ android:name="device"
+ android:translateX="24.14999"
+ android:translateY="24.25"
+ android:rotation="-135" >
+ <path
+ android:name="device_1"
+ android:pathData="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml
new file mode 100644
index 0000000..f75617f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_portrait_to_auto_rotate" >
+ <target
+ android:name="arrows"
+ android:animation="@anim/ic_portrait_to_auto_rotate_animation_arrows" />
+ <target
+ android:name="arrow_top"
+ android:animation="@anim/ic_portrait_to_auto_rotate_animation_arrow_top" />
+ <target
+ android:name="arrow_bottom"
+ android:animation="@anim/ic_portrait_to_auto_rotate_animation_arrow_bottom" />
+ <target
+ android:name="device"
+ android:animation="@anim/ic_portrait_to_auto_rotate_animation_device" />
+ <target
+ android:name="device_1"
+ android:animation="@anim/ic_portrait_to_auto_rotate_animation_device_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_airplane_off.xml b/packages/SystemUI/res/drawable/ic_qs_airplane_off.xml
deleted file mode 100644
index 79a9d409..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_airplane_off.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-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:width="64dp"
- android:height="64dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#4DFFFFFF"
- android:pathData="M26.0,18.0L26.0,7.0c0.0,-1.7 -1.3,-3.0 -3.0,-3.0c-1.7,0.0 -3.0,1.3 -3.0,3.0l0.0,7.4L35.7,30.0l6.3,2.0l0.0,-4.0L26.0,18.0zM6.0,10.5l10.0,10.0L4.0,28.0l0.0,4.0l16.0,-5.0l0.0,11.0l-4.0,3.0l0.0,3.0l7.0,-2.0l7.0,2.0l0.0,-3.0l-4.0,-3.0l0.0,-7.5L37.5,42.0l2.5,-2.5L8.5,8.0L6.0,10.5z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_airplane_on.xml b/packages/SystemUI/res/drawable/ic_qs_airplane_on.xml
deleted file mode 100644
index 5d5d257..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_airplane_on.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-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:width="64dp"
- android:height="64dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M20.4,18.0"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M42.0,32.0l0.0,-4.0L26.0,18.0L26.0,7.0c0.0,-1.7 -1.3,-3.0 -3.0,-3.0c-1.7,0.0 -3.0,1.3 -3.0,3.0l0.0,11.0L4.0,28.0l0.0,4.0l16.0,-5.0l0.0,11.0l-4.0,3.0l0.0,3.0l7.0,-2.0l7.0,2.0l0.0,-3.0l-4.0,-3.0L26.0,27.0L42.0,32.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_flashlight_off.xml b/packages/SystemUI/res/drawable/ic_qs_flashlight_off.xml
deleted file mode 100644
index d4bd76f..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_flashlight_off.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-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:width="64.0dp"
- android:height="64.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#4DFFFFFF"
- android:pathData="M14.708,11.394l14.899,14.9l0.0,-6.771c4.359,-2.353 3.831,-7.489 3.831,-7.489l0.0,-0.64L14.708,11.393998z"/>
- <path
- android:fillColor="#4DFFFFFF"
- android:pathData="M14.568,4.0l18.87,0.0l0.0,3.917l-18.87,0.0z"/>
- <path
- android:fillColor="#4DFFFFFF"
- android:pathData="M38.284,39.427l-29.767,-29.766998 -2.4750004,2.4750004 12.351999,12.351 0.0,19.514 11.213001,0.0 0.0,-8.300999 6.2019978,6.2019997z"/>
-</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_flashlight_on.xml b/packages/SystemUI/res/drawable/ic_qs_flashlight_on.xml
deleted file mode 100644
index 5514b44..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_flashlight_on.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-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:width="64.0dp"
- android:height="64.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M33.438,12.034l0.0,-0.64l-18.87,0.0l0.0,0.64c0.0,0.0 -0.581,5.189 3.826,7.523L18.394,44.0l11.213,0.0L29.606998,19.523C33.966,17.17 33.438,12.034 33.438,12.034zM24.0,27.697c-1.523,0.0 -2.757,-1.234 -2.757,-2.757c0.0,-1.523 1.234,-2.757 2.757,-2.757c1.523,0.0 2.757,1.234 2.757,2.757C26.757,26.462 25.523,27.697 24.0,27.697z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M14.568,4.0l18.87,0.0l0.0,3.917l-18.87,0.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml
deleted file mode 100644
index 4237b63..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-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:width="64dp"
- android:height="64dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#4DFFFFFF"
- android:pathData="M41.3,41.7L36.6,37.0L24.0,24.5l-7.1,-7.1L14.0,14.5L8.5,9.0L6.0,11.5l5.6,5.6c-5.1,6.3 -4.7,15.5 1.1,21.4c3.1,3.1 7.2,4.7 11.3,4.7c3.6,0.0 7.1,-1.2 10.1,-3.6l5.4,5.4l2.5,-2.5L41.3,41.7zM24.0,39.2c-3.2,0.0 -6.2,-1.2 -8.5,-3.5c-2.3,-2.3 -3.5,-5.3 -3.5,-8.5c0.0,-2.6 0.9,-5.1 2.4,-7.2l9.6,9.6L24.0,39.2zM24.0,10.2l0.0,9.2l14.5,14.5c2.7,-5.9 1.7,-13.1 -3.2,-18.0L24.0,4.5l0.0,0.0l0.0,0.0L16.6,12.0l2.8,2.8L24.0,10.2z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml
deleted file mode 100644
index 860e769..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-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:width="64dp"
- android:height="64dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M35.3,15.9L24.0,4.5l0.0,0.0l0.0,0.0L12.7,15.9c-6.2,6.2 -6.2,16.4 0.0,22.6c3.1,3.1 7.2,4.7 11.3,4.7s8.2,-1.6 11.3,-4.7C41.6,32.2 41.6,22.1 35.3,15.9zM24.0,39.2L24.0,39.2c-3.2,0.0 -6.2,-1.2 -8.5,-3.5c-2.3,-2.3 -3.5,-5.3 -3.5,-8.5s1.2,-6.2 3.5,-8.5l8.5,-8.5L24.0,39.2z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_off.xml b/packages/SystemUI/res/drawable/ic_qs_location_off.xml
deleted file mode 100644
index e0fe12e..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_location_off.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-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:width="64dp"
- android:height="64dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#4DFFFFFF"
- android:pathData="M24.0,13.0c2.8,0.0 5.0,2.2 5.0,5.0c0.0,1.5 -0.7,2.8 -1.7,3.7l7.3,7.3c2.0,-3.7 3.4,-7.6 3.4,-11.0c0.0,-7.7 -6.3,-14.0 -14.0,-14.0c-4.0,0.0 -7.5,1.6 -10.1,4.3l6.4,6.4C21.2,13.6 22.5,13.0 24.0,13.0zM32.7,32.2l-9.3,-9.3l-0.2,-0.2L6.5,6.0L4.0,8.5l6.4,6.4c-0.2,1.0 -0.4,2.0 -0.4,3.1c0.0,10.5 14.0,26.0 14.0,26.0s3.3,-3.7 6.8,-8.7l6.7,6.7l2.5,-2.5L32.7,32.2z"/>
- <path
- android:pathData="M23.5,22.9l0.0,0.0 -0.20000076,-0.19999886z"
- android:fillColor="#4DFFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_on.xml b/packages/SystemUI/res/drawable/ic_qs_location_on.xml
deleted file mode 100644
index 6a7cd53..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_location_on.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-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:width="64dp"
- android:height="64dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M24.0,4.0c-7.7,0.0 -14.0,6.3 -14.0,14.0c0.0,10.5 14.0,26.0 14.0,26.0s14.0,-15.5 14.0,-26.0C38.0,10.3 31.7,4.0 24.0,4.0zM24.0,23.0c-2.8,0.0 -5.0,-2.2 -5.0,-5.0s2.2,-5.0 5.0,-5.0c2.8,0.0 5.0,2.2 5.0,5.0S26.8,23.0 24.0,23.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml
deleted file mode 100644
index 4bb3668..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-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:width="64dp"
- android:height="64dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2.0,14.0l0.0,20.0c0.0,2.2 1.8,4.0 4.0,4.0l36.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,14.0c0.0,-2.2 -1.8,-4.0 -4.0,-4.0L6.0,10.0C3.8,10.0 2.0,11.8 2.0,14.0zM38.0,14.0l0.0,20.0L10.0,34.0L10.0,14.0L38.0,14.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml
deleted file mode 100644
index f0878c7..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-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:width="64dp"
- android:height="64dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M34.0,2.0L14.0,2.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,36.0c0.0,2.2 1.8,4.0 4.0,4.0l20.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L38.0,6.0C38.0,3.8 36.2,2.0 34.0,2.0zM34.0,38.0L14.0,38.0L14.0,10.0l20.0,0.0L34.0,38.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml
deleted file mode 100644
index 94b3a6b..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-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:width="64dp"
- android:height="64dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M16.600000,2.500000c3.300000,1.500000 5.600000,4.700000 6.000000,8.500000l1.500000,0.000000c-0.600000,-6.200000 -5.700000,-11.000000 -12.000000,-11.000000c-0.200000,0.000000 -0.400000,0.000000 -0.700000,0.000000l3.800000,3.800000L16.600000,2.500000zM10.300000,1.700000c-0.600000,-0.600000 -1.500000,-0.600000 -2.100000,0.000000L1.800000,8.100000c-0.600000,0.600000 -0.600000,1.500000 0.000000,2.100000l12.000000,12.000000c0.600000,0.600000 1.500000,0.600000 2.100000,0.000000l6.400000,-6.400000c0.600000,-0.600000 0.600000,-1.500000 0.000000,-2.100000L10.300000,1.700000zM13.400000,19.700001l-9.200000,-9.200000l6.400000,-6.400000l9.200000,9.200000L13.400000,19.700001zM7.600000,21.500000C4.300000,20.000000 2.000000,16.799999 1.600000,13.000000L0.200000,13.000000c0.500000,6.200000 5.600000,11.000000 11.900000,11.000000c0.200000,0.000000 0.400000,0.000000 0.700000,0.000000L9.000000,20.200001L7.600000,21.500000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
new file mode 100644
index 0000000..09a67e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
@@ -0,0 +1,57 @@
+<?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"
+ android:name="root"
+ android:alpha="1.0"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_signal_airplane"
+ android:translateX="21.9995"
+ android:translateY="25.73401" >
+ <group
+ android:name="ic_signal_airplane_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="0"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="plane"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <path
+ android:name="plane_1"
+ android:pathData="M 18.9439849854,7.98849487305 c 0.0,0.0 0.0,-4.0 0.0,-4.0 c 0.0,0.0 -16.0,-10.0 -16.0,-10.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,-1.70001220703 -1.30000305176,-3.0 -3.0,-3.0 c -1.69999694824,0.0 -3.0,1.29998779297 -3.0,3.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -16.0,10.0 -16.0,10.0 c 0.0,0.0 0.0,4.0 0.0,4.0 c 0.0,0.0 16.0,-5.0 16.0,-5.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -4.0,3.0 -4.0,3.0 c 0.0,0.0 0.0,3.0 0.0,3.0 c 0.0,0.0 7.0,-2.0 7.0,-2.0 c 0.0,0.0 7.0,2.0 7.0,2.0 c 0.0,0.0 0.0,-3.0 0.0,-3.0 c 0.0,0.0 -4.0,-3.0 -4.0,-3.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,0.0 16.0,5.0 16.0,5.0 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml
new file mode 100644
index 0000000..3e838e2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_signal_airplane_disable" >
+ <target
+ android:name="root"
+ android:animation="@anim/ic_signal_airplane_disable_animation_root" />
+ <target
+ android:name="ic_signal_airplane"
+ android:animation="@anim/ic_signal_airplane_disable_animation_ic_signal_airplane" />
+ <target
+ android:name="mask"
+ android:animation="@anim/ic_signal_airplane_disable_animation_mask" />
+ <target
+ android:name="cross_1"
+ android:animation="@anim/ic_signal_airplane_disable_animation_cross_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
new file mode 100644
index 0000000..ea3a15b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
@@ -0,0 +1,58 @@
+<?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"
+ android:name="root"
+ android:alpha="0.3"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_signal_airplane"
+ android:translateX="21.9995"
+ android:translateY="25.73401"
+ android:alpha="0.3" >
+ <group
+ android:name="ic_signal_airplane_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="1"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="plane"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <path
+ android:name="plane_1"
+ android:pathData="M 18.9439849854,7.98849487305 c 0.0,0.0 0.0,-4.0 0.0,-4.0 c 0.0,0.0 -16.0,-10.0 -16.0,-10.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,-1.70001220703 -1.30000305176,-3.0 -3.0,-3.0 c -1.69999694824,0.0 -3.0,1.29998779297 -3.0,3.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -16.0,10.0 -16.0,10.0 c 0.0,0.0 0.0,4.0 0.0,4.0 c 0.0,0.0 16.0,-5.0 16.0,-5.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -4.0,3.0 -4.0,3.0 c 0.0,0.0 0.0,3.0 0.0,3.0 c 0.0,0.0 7.0,-2.0 7.0,-2.0 c 0.0,0.0 7.0,2.0 7.0,2.0 c 0.0,0.0 0.0,-3.0 0.0,-3.0 c 0.0,0.0 -4.0,-3.0 -4.0,-3.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,0.0 16.0,5.0 16.0,5.0 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml
new file mode 100644
index 0000000..d64b199
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_signal_airplane_enable" >
+ <target
+ android:name="root"
+ android:animation="@anim/ic_signal_airplane_enable_animation_root" />
+ <target
+ android:name="ic_signal_airplane"
+ android:animation="@anim/ic_signal_airplane_enable_animation_ic_signal_airplane" />
+ <target
+ android:name="mask"
+ android:animation="@anim/ic_signal_airplane_enable_animation_mask" />
+ <target
+ android:name="cross_1"
+ android:animation="@anim/ic_signal_airplane_enable_animation_cross_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
new file mode 100644
index 0000000..35844b7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
@@ -0,0 +1,57 @@
+<?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"
+ android:name="root"
+ android:alpha="1.0"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_signal_flashlight"
+ android:translateX="21.9995"
+ android:translateY="25.73401" >
+ <group
+ android:name="ic_signal_flashlight_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 37.8337860107,-39.2849731445 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 8.34049987793,5.6930847168 c 0.0,0.0 0.274993896484,0.29997253418 0.274993896484,0.29997253418 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="0"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="flashlight"
+ android:translateX="25.06235"
+ android:translateY="22.48294" >
+ <path
+ android:name="light"
+ android:pathData="M -9.40809631348,-23.6970062256 c 0.0,0.0 18.8699951172,0.0 18.8699951172,0.0 c 0.0,0.0 0.0,3.91700744629 0.0,3.91700744629 c 0.0,0.0 -18.8699951172,0.0 -18.8699951172,0.0 c 0.0,0.0 0.0,-3.91700744629 0.0,-3.91700744629 Z M 9.4615020752,-15.6629943848 c 0.0,0.0 0.0,-0.639999389648 0.0,-0.639999389649 c 0.0,0.0 -18.8699951172,0.0 -18.8699951172,0.0 c 0.0,0.0 0.0,0.639999389648 0.0,0.639999389649 c 0.0,0.0 -0.581008911133,5.18899536133 3.82598876953,7.52299499512 c 0.0,0.0 0.0,24.4429931641 0.0,24.4429931641 c 0.0,0.0 11.2129974365,0.0 11.2129974365,0.0 c 0.0,0.0 0.0,-24.4769897461 0.0,-24.4769897461 c 4.35900878906,-2.35301208496 3.83100891113,-7.48899841309 3.83100891113,-7.48899841309 Z M 0.0234985351562,0 c -1.52299499512,0 -2.75700378418,-1.23399353027 -2.75700378418,-2.75700378418 c 0.0,-1.52299499512 1.23400878906,-2.75700378418 2.75700378418,-2.75700378418 c 1.52299499512,0.0 2.75700378418,1.23400878906 2.75700378418,2.75700378418 c 0.0,1.52200317383 -1.23400878906,2.75700378418 -2.75700378418,2.75700378418 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml
new file mode 100644
index 0000000..6d787ab
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_signal_flashlight_disable" >
+ <target
+ android:name="root"
+ android:animation="@anim/ic_signal_flashlight_disable_animation_root" />
+ <target
+ android:name="ic_signal_flashlight"
+ android:animation="@anim/ic_signal_flashlight_disable_animation_ic_signal_flashlight" />
+ <target
+ android:name="mask"
+ android:animation="@anim/ic_signal_flashlight_disable_animation_mask" />
+ <target
+ android:name="cross_1"
+ android:animation="@anim/ic_signal_flashlight_disable_animation_cross_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
new file mode 100644
index 0000000..93e97ee
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
@@ -0,0 +1,58 @@
+<?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"
+ android:name="root"
+ android:alpha="0.3"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_signal_flashlight"
+ android:translateX="21.9995"
+ android:translateY="25.73401"
+ android:alpha="0.3" >
+ <group
+ android:name="ic_signal_flashlight_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 37.8337860107,-39.2975769043 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 8.34049987793,5.6930847168 c 0.0,0.0 29.7749786377,29.7999725342 29.7749786377,29.7999725342 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="1"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="flashlight"
+ android:translateX="25.06235"
+ android:translateY="22.48294" >
+ <path
+ android:name="light"
+ android:pathData="M -9.40809631348,-23.6970062256 c 0.0,0.0 18.8699951172,0.0 18.8699951172,0.0 c 0.0,0.0 0.0,3.91700744629 0.0,3.91700744629 c 0.0,0.0 -18.8699951172,0.0 -18.8699951172,0.0 c 0.0,0.0 0.0,-3.91700744629 0.0,-3.91700744629 Z M 9.4615020752,-15.6629943848 c 0.0,0.0 0.0,-0.639999389648 0.0,-0.639999389649 c 0.0,0.0 -18.8699951172,0.0 -18.8699951172,0.0 c 0.0,0.0 0.0,0.639999389648 0.0,0.639999389649 c 0.0,0.0 -0.581008911133,5.18899536133 3.82598876953,7.52299499512 c 0.0,0.0 0.0,24.4429931641 0.0,24.4429931641 c 0.0,0.0 11.2129974365,0.0 11.2129974365,0.0 c 0.0,0.0 0.0,-24.4769897461 0.0,-24.4769897461 c 4.35900878906,-2.35301208496 3.83100891113,-7.48899841309 3.83100891113,-7.48899841309 Z M 0.0234985351562,0 c -1.52299499512,0 -2.75700378418,-1.23399353027 -2.75700378418,-2.75700378418 c 0.0,-1.52299499512 1.23400878906,-2.75700378418 2.75700378418,-2.75700378418 c 1.52299499512,0.0 2.75700378418,1.23400878906 2.75700378418,2.75700378418 c 0.0,1.52200317383 -1.23400878906,2.75700378418 -2.75700378418,2.75700378418 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml
new file mode 100644
index 0000000..dcfba7d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_signal_flashlight_enable" >
+ <target
+ android:name="root"
+ android:animation="@anim/ic_signal_flashlight_enable_animation_root" />
+ <target
+ android:name="ic_signal_flashlight"
+ android:animation="@anim/ic_signal_flashlight_enable_animation_ic_signal_flashlight" />
+ <target
+ android:name="mask"
+ android:animation="@anim/ic_signal_flashlight_enable_animation_mask" />
+ <target
+ android:name="cross_1"
+ android:animation="@anim/ic_signal_flashlight_enable_animation_cross_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
new file mode 100644
index 0000000..439851d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
@@ -0,0 +1,57 @@
+<?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"
+ android:name="root"
+ android:alpha="1.0"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_signal_location"
+ android:translateX="21.9995"
+ android:translateY="25.73401" >
+ <group
+ android:name="ic_signal_location_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 38.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 7.3759765625,7.55284118652 7.3759765625,7.55284118652 c 0.0,0.0 -2.61698913574,2.0938873291 -2.61698913574,2.0938873291 c 0.0,0.0 -7.57595825195,-7.56428527832 -7.57595825195,-7.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 6.44050598145,1.9430847168 c 0.0,0.0 0.374984741211,0.399978637695 0.374984741211,0.399978637695 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="0"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="location"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <path
+ android:name="pin"
+ android:pathData="M 1.76899719238,-20.011505127 c -7.69999694824,0.0 -14.0,6.30000305176 -14.0,14.0 c 0.0,10.5 14.0,26.0 14.0,26.0 c 0.0,0.0 14.0,-15.5 14.0,-26.0 c 0.0,-7.69999694824 -6.30000305176,-14.0 -14.0,-14.0 Z M 1.76899719238,-1.01150512695 c -2.80000305176,0.0 -5.0,-2.19999694824 -5.0,-5.0 c 0.0,-2.80000305176 2.19999694824,-5.0 5.0,-5.0 c 2.80000305176,0.0 5.0,2.19999694824 5.0,5.0 c 0.0,2.80000305176 -2.19999694824,5.0 -5.0,5.0 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml
new file mode 100644
index 0000000..a219c54
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_signal_location_disable" >
+ <target
+ android:name="root"
+ android:animation="@anim/ic_signal_location_disable_animation_root" />
+ <target
+ android:name="ic_signal_location"
+ android:animation="@anim/ic_signal_location_disable_animation_ic_signal_location" />
+ <target
+ android:name="mask"
+ android:animation="@anim/ic_signal_location_disable_animation_mask" />
+ <target
+ android:name="cross_1"
+ android:animation="@anim/ic_signal_location_disable_animation_cross_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
new file mode 100644
index 0000000..c800ef4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
@@ -0,0 +1,58 @@
+<?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"
+ android:name="root"
+ android:alpha="0.3"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_signal_location"
+ android:translateX="21.9995"
+ android:translateY="25.73401"
+ android:alpha="0.3" >
+ <group
+ android:name="ic_signal_location_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 38.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,41.1153411865 40.9884796143,41.1153411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-41.1267852783 -41.1884460449,-41.1267852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 6.44050598145,1.9430847168 c 0.0,0.0 33.5749816895,33.4499664307 33.5749816895,33.4499664307 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="1"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="location"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <path
+ android:name="pin"
+ android:pathData="M 1.76899719238,-20.011505127 c -7.69999694824,0.0 -14.0,6.30000305176 -14.0,14.0 c 0.0,10.5 14.0,26.0 14.0,26.0 c 0.0,0.0 14.0,-15.5 14.0,-26.0 c 0.0,-7.69999694824 -6.30000305176,-14.0 -14.0,-14.0 Z M 1.76899719238,-1.01150512695 c -2.80000305176,0.0 -5.0,-2.19999694824 -5.0,-5.0 c 0.0,-2.80000305176 2.19999694824,-5.0 5.0,-5.0 c 2.80000305176,0.0 5.0,2.19999694824 5.0,5.0 c 0.0,2.80000305176 -2.19999694824,5.0 -5.0,5.0 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml
new file mode 100644
index 0000000..bbc1d73
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_signal_location_enable" >
+ <target
+ android:name="root"
+ android:animation="@anim/ic_signal_location_enable_animation_root" />
+ <target
+ android:name="ic_signal_location"
+ android:animation="@anim/ic_signal_location_enable_animation_ic_signal_location" />
+ <target
+ android:name="mask"
+ android:animation="@anim/ic_signal_location_enable_animation_mask" />
+ <target
+ android:name="cross_1"
+ android:animation="@anim/ic_signal_location_enable_animation_cross_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/interpolator/ic_invert_colors_disable_cross_1_pathdata_interpolator.xml b/packages/SystemUI/res/interpolator/ic_invert_colors_disable_cross_1_pathdata_interpolator.xml
new file mode 100644
index 0000000..bc0442f
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_invert_colors_disable_cross_1_pathdata_interpolator.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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0,0 c 0.166666667,0 0.2,1 1,1" />
diff --git a/packages/SystemUI/res/interpolator/ic_invert_colors_enable_cross_1_pathdata_interpolator.xml b/packages/SystemUI/res/interpolator/ic_invert_colors_enable_cross_1_pathdata_interpolator.xml
new file mode 100644
index 0000000..bc90d28
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_invert_colors_enable_cross_1_pathdata_interpolator.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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0,0 c 0.8,0 0.833333333,1 1,1" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_1.xml b/packages/SystemUI/res/interpolator/ic_invert_colors_enable_mask_pathdata_interpolator.xml
index 601cfc6..f7072f2 100644
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_1.xml
+++ b/packages/SystemUI/res/interpolator/ic_invert_colors_enable_mask_pathdata_interpolator.xml
@@ -1,4 +1,6 @@
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?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.
@@ -13,4 +15,4 @@
limitations under the License.
-->
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.33333333,0.0 0.202777547991,1.0 1.0,1.0" />
+ android:pathData="M 0,0 c 0.8,0 0.6,1 1,1" />
diff --git a/packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.xml b/packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.xml
new file mode 100644
index 0000000..76f5667
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0,0 c 0.458031162,0 0.299442342,0.748308635 1,1" />
diff --git a/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml b/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml
new file mode 100644
index 0000000..ac27e4d
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0,0 c 0.4,0.143709151 0.2,1 1,1" />
diff --git a/packages/SystemUI/res/interpolator/ic_signal_airplane_disable_cross_1_pathdata_interpolator.xml b/packages/SystemUI/res/interpolator/ic_signal_airplane_disable_cross_1_pathdata_interpolator.xml
new file mode 100644
index 0000000..bc0442f
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_signal_airplane_disable_cross_1_pathdata_interpolator.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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0,0 c 0.166666667,0 0.2,1 1,1" />
diff --git a/packages/SystemUI/res/interpolator/ic_signal_airplane_enable_cross_1_pathdata_interpolator.xml b/packages/SystemUI/res/interpolator/ic_signal_airplane_enable_cross_1_pathdata_interpolator.xml
new file mode 100644
index 0000000..bc90d28
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_signal_airplane_enable_cross_1_pathdata_interpolator.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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0,0 c 0.8,0 0.833333333,1 1,1" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_3.xml b/packages/SystemUI/res/interpolator/ic_signal_airplane_enable_mask_pathdata_interpolator.xml
index 7b0af97..f7072f2 100644
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_3.xml
+++ b/packages/SystemUI/res/interpolator/ic_signal_airplane_enable_mask_pathdata_interpolator.xml
@@ -1,4 +1,6 @@
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?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.
@@ -13,4 +15,4 @@
limitations under the License.
-->
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.649706648701,0.0 0.884285938423,1.92358061843 1.0,1.0" />
+ android:pathData="M 0,0 c 0.8,0 0.6,1 1,1" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_2.xml b/packages/SystemUI/res/interpolator/ic_signal_flashlight_enable_cross_1_pathdata_interpolator.xml
index 5011ef9..f7072f2 100644
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_2.xml
+++ b/packages/SystemUI/res/interpolator/ic_signal_flashlight_enable_cross_1_pathdata_interpolator.xml
@@ -1,4 +1,6 @@
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?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.
@@ -13,4 +15,4 @@
limitations under the License.
-->
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.0103034467173,0.0 0.701918866569,1.0 1.0,1.0" />
+ android:pathData="M 0,0 c 0.8,0 0.6,1 1,1" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_1.xml b/packages/SystemUI/res/interpolator/ic_signal_flashlight_enable_mask_pathdata_interpolator.xml
index 601cfc6..f7072f2 100644
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_1.xml
+++ b/packages/SystemUI/res/interpolator/ic_signal_flashlight_enable_mask_pathdata_interpolator.xml
@@ -1,4 +1,6 @@
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?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.
@@ -13,4 +15,4 @@
limitations under the License.
-->
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.33333333,0.0 0.202777547991,1.0 1.0,1.0" />
+ android:pathData="M 0,0 c 0.8,0 0.6,1 1,1" />
diff --git a/packages/SystemUI/res/interpolator/ic_signal_location_enable_cross_1_pathdata_interpolator.xml b/packages/SystemUI/res/interpolator/ic_signal_location_enable_cross_1_pathdata_interpolator.xml
new file mode 100644
index 0000000..f7072f2
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_signal_location_enable_cross_1_pathdata_interpolator.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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0,0 c 0.8,0 0.6,1 1,1" />
diff --git a/packages/SystemUI/res/interpolator/ic_signal_location_enable_mask_pathdata_interpolator.xml b/packages/SystemUI/res/interpolator/ic_signal_location_enable_mask_pathdata_interpolator.xml
new file mode 100644
index 0000000..f7072f2
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_signal_location_enable_mask_pathdata_interpolator.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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0,0 c 0.8,0 0.6,1 1,1" />
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6e6f302..51ef0c3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -63,6 +63,8 @@
<!-- thickness (height) of the navigation bar on phones that require it -->
<dimen name="navigation_bar_size">@*android:dimen/navigation_bar_height</dimen>
+ <!-- Minimum swipe distance to catch the swipe gestures to invoke assist or switch tasks. -->
+ <dimen name="navigation_bar_min_swipe_distance">48dp</dimen>
<!-- thickness (height) of the dead zone at the top of the navigation bar,
reducing false presses on navbar buttons; approx 2mm -->
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 4e93cd8..4a9eb55 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -35,5 +35,6 @@
<item type="id" name="top_inset_animator_start_value_tag"/>
<item type="id" name="height_animator_start_value_tag"/>
<item type="id" name="doze_saved_filter_tag"/>
+ <item type="id" name="qs_icon_tag"/>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4af8499..172aaf6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -364,7 +364,7 @@ public class KeyguardViewMediator extends SystemUI {
// only force lock screen in case of missing sim if user hasn't
// gone through setup wizard
synchronized (this) {
- if (!mUpdateMonitor.isDeviceProvisioned()) {
+ if (shouldWaitForProvisioning()) {
if (!isShowing()) {
if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
+ " we need to show the keyguard since the "
@@ -493,8 +493,7 @@ public class KeyguardViewMediator extends SystemUI {
mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());
// Assume keyguard is showing (unless it's disabled) until we know for sure...
- mShowing = (mUpdateMonitor.isDeviceProvisioned() || mLockPatternUtils.isSecure())
- && !mLockPatternUtils.isLockScreenDisabled();
+ mShowing = !shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled();
mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
mViewMediatorCallback, mLockPatternUtils);
@@ -783,7 +782,7 @@ public class KeyguardViewMediator extends SystemUI {
public void verifyUnlock(IKeyguardExitCallback callback) {
synchronized (this) {
if (DEBUG) Log.d(TAG, "verifyUnlock");
- if (!mUpdateMonitor.isDeviceProvisioned()) {
+ if (shouldWaitForProvisioning()) {
// don't allow this api when the device isn't provisioned
if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned");
try {
@@ -873,7 +872,7 @@ public class KeyguardViewMediator extends SystemUI {
* was suppressed by an app that disabled the keyguard or we haven't been provisioned yet.
*/
public boolean isInputRestricted() {
- return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned();
+ return mShowing || mNeedToReshowWhenReenabled || shouldWaitForProvisioning();
}
/**
@@ -905,14 +904,13 @@ public class KeyguardViewMediator extends SystemUI {
// if the setup wizard hasn't run yet, don't show
final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
false);
- final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
final IccCardConstants.State state = mUpdateMonitor.getSimState();
final boolean lockedOrMissing = state.isPinLocked()
|| ((state == IccCardConstants.State.ABSENT
|| state == IccCardConstants.State.PERM_DISABLED)
&& requireSim);
- if (!lockedOrMissing && !provisioned) {
+ if (!lockedOrMissing && shouldWaitForProvisioning()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
+ " and the sim is not locked or missing");
return;
@@ -935,6 +933,10 @@ public class KeyguardViewMediator extends SystemUI {
showLocked(options);
}
+ private boolean shouldWaitForProvisioning() {
+ return !mUpdateMonitor.isDeviceProvisioned() && !isSecure();
+ }
+
/**
* Dismiss the keyguard through the security layers.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 54a8414..1ddd352 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -203,7 +203,7 @@ public class QSPanel extends ViewGroup {
}
}
- private void refreshAllTiles() {
+ public void refreshAllTiles() {
for (TileRecord r : mRecords) {
r.tile.refreshState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 6ef6e9e..2a66484 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -18,11 +18,13 @@ package com.android.systemui.qs;
import android.content.Context;
import android.content.Intent;
+import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
+import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
@@ -299,10 +301,91 @@ public abstract class QSTile<TState extends State> implements Listenable {
}
}
+ public static abstract class Icon {
+ abstract public Drawable getDrawable(Context context);
+
+ @Override
+ public int hashCode() {
+ return Icon.class.hashCode();
+ }
+ }
+
+ public static class ResourceIcon extends Icon {
+ private static final SparseArray<Icon> ICONS = new SparseArray<Icon>();
+
+ private final int mResId;
+
+ private ResourceIcon(int resId) {
+ mResId = resId;
+ }
+
+ public static Icon get(int resId) {
+ Icon icon = ICONS.get(resId);
+ if (icon == null) {
+ icon = new ResourceIcon(resId);
+ ICONS.put(resId, icon);
+ }
+ return icon;
+ }
+
+ @Override
+ public Drawable getDrawable(Context context) {
+ return context.getDrawable(mResId);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof ResourceIcon && ((ResourceIcon) o).mResId == mResId;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ResourceIcon[resId=0x%08x]", mResId);
+ }
+ }
+
+ protected class AnimationIcon extends ResourceIcon {
+ private boolean mAllowAnimation;
+
+ public AnimationIcon(int resId) {
+ super(resId);
+ }
+
+ public void setAllowAnimation(boolean allowAnimation) {
+ mAllowAnimation = allowAnimation;
+ }
+
+ @Override
+ public Drawable getDrawable(Context context) {
+ // workaround: get a clean state for every new AVD
+ final AnimatedVectorDrawable d = (AnimatedVectorDrawable) super.getDrawable(context)
+ .getConstantState().newDrawable();
+ d.start();
+ if (mAllowAnimation) {
+ mAllowAnimation = false;
+ } else {
+ d.stop(); // skip directly to end state
+ }
+ return d;
+ }
+ }
+
+ protected enum UserBoolean {
+ USER_TRUE(true, true),
+ USER_FALSE(true, false),
+ BACKGROUND_TRUE(false, true),
+ BACKGROUND_FALSE(false, false);
+ public final boolean value;
+ public final boolean userInitiated;
+ private UserBoolean(boolean userInitiated, boolean value) {
+ this.value = value;
+ this.userInitiated = userInitiated;
+ }
+ }
+
public static class State {
public boolean visible;
- public int iconId;
- public Drawable icon;
+ public Icon icon;
public String label;
public String contentDescription;
public String dualLabelContentDescription;
@@ -312,7 +395,6 @@ public abstract class QSTile<TState extends State> implements Listenable {
if (other == null) throw new IllegalArgumentException();
if (!other.getClass().equals(getClass())) throw new IllegalArgumentException();
final boolean changed = other.visible != visible
- || other.iconId != iconId
|| !Objects.equals(other.icon, icon)
|| !Objects.equals(other.label, label)
|| !Objects.equals(other.contentDescription, contentDescription)
@@ -320,7 +402,6 @@ public abstract class QSTile<TState extends State> implements Listenable {
|| !Objects.equals(other.dualLabelContentDescription,
dualLabelContentDescription);
other.visible = visible;
- other.iconId = iconId;
other.icon = icon;
other.label = label;
other.contentDescription = contentDescription;
@@ -335,9 +416,8 @@ public abstract class QSTile<TState extends State> implements Listenable {
}
protected StringBuilder toStringBuilder() {
- final StringBuilder sb = new StringBuilder( getClass().getSimpleName()).append('[');
+ final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
sb.append("visible=").append(visible);
- sb.append(",iconId=").append(iconId);
sb.append(",icon=").append(icon);
sb.append(",label=").append(label);
sb.append(",contentDescription=").append(contentDescription);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index d5c90d0..3d0f47c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -21,6 +21,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Typeface;
+import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Handler;
@@ -39,6 +40,8 @@ import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile.State;
+import java.util.Objects;
+
/** View that represents a standard quick settings tile. **/
public class QSTileView extends ViewGroup {
private static final Typeface CONDENSED = Typeface.create("sans-serif-condensed",
@@ -60,6 +63,7 @@ public class QSTileView extends ViewGroup {
private boolean mDual;
private OnClickListener mClickPrimary;
private OnClickListener mClickSecondary;
+ private Drawable mTileBackground;
private RippleDrawable mRipple;
public QSTileView(Context context) {
@@ -72,6 +76,7 @@ public class QSTileView extends ViewGroup {
mTilePaddingBelowIconPx = res.getDimensionPixelSize(R.dimen.qs_tile_padding_below_icon);
mDualTileVerticalPaddingPx =
res.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_vertical);
+ mTileBackground = newTileBackground();
recreateLabel();
setClipChildren(false);
@@ -172,22 +177,21 @@ public class QSTileView extends ViewGroup {
if (changed) {
recreateLabel();
}
- Drawable tileBackground = getTileBackground();
- if (tileBackground instanceof RippleDrawable) {
- setRipple((RippleDrawable) tileBackground);
+ if (mTileBackground instanceof RippleDrawable) {
+ setRipple((RippleDrawable) mTileBackground);
}
if (dual) {
mTopBackgroundView.setOnClickListener(mClickPrimary);
setOnClickListener(null);
setClickable(false);
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
- mTopBackgroundView.setBackground(tileBackground);
+ mTopBackgroundView.setBackground(mTileBackground);
} else {
mTopBackgroundView.setOnClickListener(null);
mTopBackgroundView.setClickable(false);
setOnClickListener(mClickPrimary);
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- setBackground(tileBackground);
+ setBackground(mTileBackground);
}
mTopBackgroundView.setFocusable(dual);
setFocusable(!dual);
@@ -214,7 +218,7 @@ public class QSTileView extends ViewGroup {
return icon;
}
- private Drawable getTileBackground() {
+ private Drawable newTileBackground() {
final int[] attrs = new int[] { android.R.attr.selectableItemBackgroundBorderless };
final TypedArray ta = mContext.obtainStyledAttributes(attrs);
final Drawable d = ta.getDrawable(0);
@@ -285,16 +289,7 @@ public class QSTileView extends ViewGroup {
protected void handleStateChanged(QSTile.State state) {
if (mIcon instanceof ImageView) {
- ImageView iv = (ImageView) mIcon;
- if (state.icon != null) {
- iv.setImageDrawable(state.icon);
- } else if (state.iconId > 0) {
- iv.setImageResource(state.iconId);
- }
- Drawable drawable = iv.getDrawable();
- if (state.autoMirrorDrawable && drawable != null) {
- drawable.setAutoMirrored(true);
- }
+ setIcon((ImageView) mIcon, state);
}
if (mDual) {
mDualLabel.setText(state.label);
@@ -306,6 +301,22 @@ public class QSTileView extends ViewGroup {
}
}
+ protected void setIcon(ImageView iv, QSTile.State state) {
+ if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
+ Drawable d = state.icon != null ? state.icon.getDrawable(mContext) : null;
+ if (d != null && state.autoMirrorDrawable) {
+ d.setAutoMirrored(true);
+ }
+ iv.setImageDrawable(d);
+ iv.setTag(R.id.qs_icon_tag, state.icon);
+ if (d instanceof Animatable) {
+ if (!iv.isShown()) {
+ ((Animatable) d).stop(); // skip directly to end state
+ }
+ }
+ }
+ }
+
public void onStateChanged(QSTile.State state) {
mHandler.obtainMessage(H.STATE_CHANGED, state).sendToTarget();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index cfcd74e..9ac7944 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -104,7 +104,7 @@ public final class SignalTileView extends QSTileView {
protected void handleStateChanged(QSTile.State state) {
super.handleStateChanged(state);
final SignalState s = (SignalState) state;
- mSignal.setImageResource(s.iconId);
+ setIcon(mSignal, s);
if (s.overlayIconId > 0) {
mOverlay.setVisibility(VISIBLE);
mOverlay.setImageResource(s.overlayIconId);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 51401c8..2dd02a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -29,6 +29,10 @@ import com.android.systemui.qs.QSTile;
/** Quick settings tile: Airplane mode **/
public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
+ private final AnimationIcon mEnable =
+ new AnimationIcon(R.drawable.ic_signal_airplane_enable_animation);
+ private final AnimationIcon mDisable =
+ new AnimationIcon(R.drawable.ic_signal_airplane_disable_animation);
private final GlobalSetting mSetting;
private boolean mListening;
@@ -52,6 +56,8 @@ public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
@Override
public void handleClick() {
setEnabled(!mState.value);
+ mEnable.setAllowAnimation(true);
+ mDisable.setAllowAnimation(true);
}
private void setEnabled(boolean enabled) {
@@ -68,11 +74,11 @@ public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
state.visible = true;
state.label = mContext.getString(R.string.quick_settings_airplane_mode_label);
if (airplaneMode) {
- state.iconId = R.drawable.ic_qs_airplane_on;
+ state.icon = mEnable;
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_airplane_on);
} else {
- state.iconId = R.drawable.ic_qs_airplane_off;
+ state.icon = mDisable;
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_airplane_off);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 84bfb8f..4d77348 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -92,17 +92,17 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
if (enabled) {
state.label = null;
if (connected) {
- state.iconId = R.drawable.ic_qs_bluetooth_connected;
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connected);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_bluetooth_connected);
state.label = mController.getLastDeviceName();
} else if (connecting) {
- state.iconId = R.drawable.ic_qs_bluetooth_connecting;
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connecting);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_bluetooth_connecting);
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
} else {
- state.iconId = R.drawable.ic_qs_bluetooth_on;
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_on);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_bluetooth_on);
}
@@ -110,7 +110,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
}
} else {
- state.iconId = R.drawable.ic_qs_bluetooth_off;
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_off);
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_bluetooth_off);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 8304291..5bf6fb5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -107,7 +107,8 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
if (!state.value && connecting) {
state.label = mContext.getString(R.string.quick_settings_connecting);
}
- state.iconId = state.value ? R.drawable.ic_qs_cast_on : R.drawable.ic_qs_cast_off;
+ state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_cast_on
+ : R.drawable.ic_qs_cast_off);
mDetailAdapter.updateItems(devices);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 359a259..178590b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -87,16 +87,17 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
if (cb == null) return;
final Resources r = mContext.getResources();
- state.iconId = cb.noSim ? R.drawable.ic_qs_no_sim
+ final int iconId = cb.noSim ? R.drawable.ic_qs_no_sim
: !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
: cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
: R.drawable.ic_qs_signal_no_signal;
+ state.icon = ResourceIcon.get(iconId);
state.isOverlayIconWide = cb.isDataTypeIconWide;
state.autoMirrorDrawable = !cb.noSim;
state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) && !cb.wifiConnected
? cb.dataTypeIconId
: 0;
- state.filter = state.iconId != R.drawable.ic_qs_no_sim;
+ state.filter = iconId != R.drawable.ic_qs_no_sim;
state.activityIn = cb.enabled && cb.activityIn;
state.activityOut = cb.enabled && cb.activityOut;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 7ba1dc0..a19c29f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -26,6 +26,10 @@ import com.android.systemui.qs.UsageTracker;
/** Quick settings tile: Invert colors **/
public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
+ private final AnimationIcon mEnable
+ = new AnimationIcon(R.drawable.ic_invert_colors_enable_animation);
+ private final AnimationIcon mDisable
+ = new AnimationIcon(R.drawable.ic_invert_colors_disable_animation);
private final SecureSetting mSetting;
private final UsageTracker mUsageTracker;
@@ -79,6 +83,8 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleClick() {
mSetting.setValue(mState.value ? 0 : 1);
+ mEnable.setAllowAnimation(true);
+ mDisable.setAllowAnimation(true);
}
@Override
@@ -88,7 +94,7 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
state.visible = enabled || mUsageTracker.isRecentlyUsed();
state.value = enabled;
state.label = mContext.getString(R.string.quick_settings_inversion_label);
- state.iconId = enabled ? R.drawable.ic_qs_inversion_on : R.drawable.ic_qs_inversion_off;
+ state.icon = enabled ? mEnable : mDisable;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index e6b7f02..5c1a317 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -31,6 +31,10 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
* still available because it was recently on. */
private static final long RECENTLY_ON_DURATION_MILLIS = 500;
+ private final AnimationIcon mEnable
+ = new AnimationIcon(R.drawable.ic_signal_flashlight_enable_animation);
+ private final AnimationIcon mDisable
+ = new AnimationIcon(R.drawable.ic_signal_flashlight_disable_animation);
private final FlashlightController mFlashlightController;
private long mWasLastOn;
@@ -66,7 +70,7 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
}
boolean newState = !mState.value;
mFlashlightController.setFlashlight(newState);
- refreshState(newState);
+ refreshState(newState ? UserBoolean.USER_TRUE : UserBoolean.USER_FALSE);
}
@Override
@@ -75,8 +79,8 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
mWasLastOn = SystemClock.uptimeMillis();
}
- if (arg instanceof Boolean) {
- state.value = (Boolean) arg;
+ if (arg instanceof UserBoolean) {
+ state.value = ((UserBoolean) arg).value;
}
if (!state.value && mWasLastOn != 0) {
@@ -92,8 +96,9 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
// the camera is not available while it is being used for the flashlight.
state.visible = mWasLastOn != 0 || mFlashlightController.isAvailable();
state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
- state.iconId = state.value
- ? R.drawable.ic_qs_flashlight_on : R.drawable.ic_qs_flashlight_off;
+ final AnimationIcon icon = state.value ? mEnable : mDisable;
+ icon.setAllowAnimation(arg instanceof UserBoolean && ((UserBoolean) arg).userInitiated);
+ state.icon = icon;
int onOrOffId = state.value
? R.string.accessibility_quick_settings_flashlight_on
: R.string.accessibility_quick_settings_flashlight_off;
@@ -111,12 +116,12 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
@Override
public void onFlashlightOff() {
- refreshState(false);
+ refreshState(UserBoolean.BACKGROUND_FALSE);
}
@Override
public void onFlashlightError() {
- refreshState(false);
+ refreshState(UserBoolean.BACKGROUND_FALSE);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index b30a1d3..64dab85 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -71,8 +71,8 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
state.label = mContext.getString(R.string.quick_settings_hotspot_label);
state.value = mController.isHotspotEnabled();
- state.iconId = state.visible && state.value ? R.drawable.ic_qs_hotspot_on
- : R.drawable.ic_qs_hotspot_off;
+ state.icon = ResourceIcon.get(state.visible && state.value ? R.drawable.ic_qs_hotspot_on
+ : R.drawable.ic_qs_hotspot_off);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 58587e6..6fb9cd8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -31,6 +31,9 @@ import android.util.Log;
import com.android.systemui.qs.QSTile;
+import java.util.Arrays;
+import java.util.Objects;
+
public class IntentTile extends QSTile<QSTile.State> {
public static final String PREFIX = "intent(";
@@ -96,13 +99,11 @@ public class IntentTile extends QSTile<QSTile.State> {
state.visible = intent.getBooleanExtra("visible", true);
state.contentDescription = intent.getStringExtra("contentDescription");
state.label = intent.getStringExtra("label");
- state.iconId = 0;
state.icon = null;
final byte[] iconBitmap = intent.getByteArrayExtra("iconBitmap");
if (iconBitmap != null) {
try {
- final Bitmap b = BitmapFactory.decodeByteArray(iconBitmap, 0, iconBitmap.length);
- state.icon = new BitmapDrawable(mContext.getResources(), b);
+ state.icon = new BytesIcon(iconBitmap);
} catch (Throwable t) {
Log.w(TAG, "Error loading icon bitmap, length " + iconBitmap.length, t);
}
@@ -111,9 +112,9 @@ public class IntentTile extends QSTile<QSTile.State> {
if (iconId != 0) {
final String iconPackage = intent.getStringExtra("iconPackage");
if (!TextUtils.isEmpty(iconPackage)) {
- state.icon = getPackageDrawable(iconPackage, iconId);
+ state.icon = new PackageDrawableIcon(iconPackage, iconId);
} else {
- state.iconId = iconId;
+ state.icon = ResourceIcon.get(iconId);
}
}
}
@@ -121,19 +122,66 @@ public class IntentTile extends QSTile<QSTile.State> {
mOnClickUri = intent.getStringExtra("onClickUri");
}
- private Drawable getPackageDrawable(String pkg, int id) {
- try {
- return mContext.createPackageContext(pkg, 0).getDrawable(id);
- } catch (Throwable t) {
- Log.w(TAG, "Error loading package drawable pkg=" + pkg + " id=" + id, t);
- return null;
- }
- }
-
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
refreshState(intent);
}
};
+
+ private static class BytesIcon extends Icon {
+ private final byte[] mBytes;
+
+ public BytesIcon(byte[] bytes) {
+ mBytes = bytes;
+ }
+
+ @Override
+ public Drawable getDrawable(Context context) {
+ final Bitmap b = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length);
+ return new BitmapDrawable(context.getResources(), b);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof BytesIcon && Arrays.equals(((BytesIcon) o).mBytes, mBytes);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("BytesIcon[len=%s]", mBytes.length);
+ }
+ }
+
+ private class PackageDrawableIcon extends Icon {
+ private final String mPackage;
+ private final int mResId;
+
+ public PackageDrawableIcon(String pkg, int resId) {
+ mPackage = pkg;
+ mResId = resId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof PackageDrawableIcon)) return false;
+ final PackageDrawableIcon other = (PackageDrawableIcon) o;
+ return Objects.equals(other.mPackage, mPackage) && other.mResId == mResId;
+ }
+
+ @Override
+ public Drawable getDrawable(Context context) {
+ try {
+ return context.createPackageContext(mPackage, 0).getDrawable(mResId);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error loading package drawable pkg=" + mPackage + " id=" + mResId, t);
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("PackageDrawableIcon[pkg=%s,id=0x%08x]", mPackage, mResId);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index d1dc5d2..11ec722 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -25,6 +25,11 @@ import com.android.systemui.statusbar.policy.LocationController.LocationSettings
/** Quick settings tile: Location **/
public class LocationTile extends QSTile<QSTile.BooleanState> {
+ private final AnimationIcon mEnable =
+ new AnimationIcon(R.drawable.ic_signal_location_enable_animation);
+ private final AnimationIcon mDisable =
+ new AnimationIcon(R.drawable.ic_signal_location_disable_animation);
+
private final LocationController mController;
private final KeyguardMonitor mKeyguard;
private final Callback mCallback = new Callback();
@@ -55,6 +60,8 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
protected void handleClick() {
final boolean wasEnabled = (Boolean) mState.value;
mController.setLocationEnabled(!wasEnabled);
+ mEnable.setAllowAnimation(true);
+ mDisable.setAllowAnimation(true);
}
@Override
@@ -67,12 +74,12 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
state.visible = !mKeyguard.isShowing();
state.value = locationEnabled;
if (locationEnabled) {
- state.iconId = R.drawable.ic_qs_location_on;
+ state.icon = mEnable;
state.label = mContext.getString(R.string.quick_settings_location_label);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_location_on);
} else {
- state.iconId = R.drawable.ic_qs_location_off;
+ state.icon = mDisable;
state.label = mContext.getString(R.string.quick_settings_location_label);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_location_off);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index ae40a4d..f46b9a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -17,7 +17,6 @@
package com.android.systemui.qs.tiles;
import android.content.res.Configuration;
-import android.content.res.Resources;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
@@ -26,6 +25,15 @@ import com.android.systemui.statusbar.policy.RotationLockController.RotationLock
/** Quick settings tile: Rotation **/
public class RotationLockTile extends QSTile<QSTile.BooleanState> {
+ private final AnimationIcon mPortraitToAuto
+ = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation);
+ private final AnimationIcon mAutoToPortrait
+ = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation);
+
+ private final AnimationIcon mLandscapeToAuto
+ = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation);
+ private final AnimationIcon mAutoToLandscape
+ = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation);
private final RotationLockController mController;
@@ -51,30 +59,34 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleClick() {
if (mController == null) return;
- mController.setRotationLocked(!mState.value);
+ final boolean newState = !mState.value;
+ mController.setRotationLocked(newState);
+ refreshState(newState ? UserBoolean.USER_TRUE : UserBoolean.USER_FALSE);
}
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
if (mController == null) return;
- final boolean rotationLocked = mController.isRotationLocked();
+ final boolean rotationLocked = arg != null ? ((UserBoolean) arg).value
+ : mController.isRotationLocked();
+ final boolean userInitiated = arg != null ? ((UserBoolean) arg).userInitiated : false;
state.visible = mController.isRotationLockAffordanceVisible();
- final Resources res = mContext.getResources();
state.value = rotationLocked;
+ final boolean portrait = mContext.getResources().getConfiguration().orientation
+ != Configuration.ORIENTATION_LANDSCAPE;
+ final AnimationIcon icon;
if (rotationLocked) {
- final boolean portrait = res.getConfiguration().orientation
- != Configuration.ORIENTATION_LANDSCAPE;
final int label = portrait ? R.string.quick_settings_rotation_locked_portrait_label
: R.string.quick_settings_rotation_locked_landscape_label;
- final int icon = portrait ? R.drawable.ic_qs_rotation_portrait
- : R.drawable.ic_qs_rotation_landscape;
state.label = mContext.getString(label);
- state.icon = mContext.getDrawable(icon);
+ icon = portrait ? mAutoToPortrait : mAutoToLandscape;
} else {
state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
- state.icon = res.getDrawable(R.drawable.ic_qs_rotation_unlocked);
+ icon = portrait ? mPortraitToAuto : mLandscapeToAuto;
}
- state.contentDescription = getAccessibilityString(
+ icon.setAllowAnimation(userInitiated);
+ state.icon = icon;
+ state.contentDescription = getAccessibilityString(rotationLocked,
R.string.accessibility_rotation_lock_on_portrait,
R.string.accessibility_rotation_lock_on_landscape,
R.string.accessibility_rotation_lock_off);
@@ -83,14 +95,16 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
/**
* Get the correct accessibility string based on the state
*
+ * @param locked Whether or not rotation is locked.
* @param idWhenPortrait The id which should be used when locked in portrait.
* @param idWhenLandscape The id which should be used when locked in landscape.
* @param idWhenOff The id which should be used when the rotation lock is off.
* @return
*/
- private String getAccessibilityString(int idWhenPortrait, int idWhenLandscape, int idWhenOff) {
+ private String getAccessibilityString(boolean locked, int idWhenPortrait, int idWhenLandscape,
+ int idWhenOff) {
int stringID;
- if (mState.value) {
+ if (locked) {
final boolean portrait = mContext.getResources().getConfiguration().orientation
!= Configuration.ORIENTATION_LANDSCAPE;
stringID = portrait ? idWhenPortrait: idWhenLandscape;
@@ -102,7 +116,7 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
@Override
protected String composeChangeAnnouncement() {
- return getAccessibilityString(
+ return getAccessibilityString(mState.value,
R.string.accessibility_rotation_lock_on_portrait_changed,
R.string.accessibility_rotation_lock_on_landscape_changed,
R.string.accessibility_rotation_lock_off_changed);
@@ -111,7 +125,8 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
private final RotationLockControllerCallback mCallback = new RotationLockControllerCallback() {
@Override
public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
- refreshState();
+ refreshState(rotationLocked ? UserBoolean.BACKGROUND_TRUE
+ : UserBoolean.BACKGROUND_FALSE);
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 20c4ee8..7aa884e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -120,19 +120,19 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
final String signalContentDescription;
final Resources r = mContext.getResources();
if (!state.enabled) {
- state.iconId = R.drawable.ic_qs_wifi_disabled;
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_disabled);
state.label = r.getString(R.string.quick_settings_wifi_label);
signalContentDescription = r.getString(R.string.accessibility_wifi_off);
} else if (wifiConnected) {
- state.iconId = cb.wifiSignalIconId;
+ state.icon = ResourceIcon.get(cb.wifiSignalIconId);
state.label = removeDoubleQuotes(cb.enabledDesc);
signalContentDescription = cb.wifiSignalContentDescription;
} else if (wifiNotConnected) {
- state.iconId = R.drawable.ic_qs_wifi_0;
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_0);
state.label = r.getString(R.string.quick_settings_wifi_label);
signalContentDescription = r.getString(R.string.accessibility_no_wifi);
} else {
- state.iconId = R.drawable.ic_qs_wifi_no_network;
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_no_network);
state.label = r.getString(R.string.quick_settings_wifi_label);
signalContentDescription = r.getString(R.string.accessibility_wifi_off);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 2a782cc..4c3460e 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -728,7 +728,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
final ActivityManager am = (ActivityManager)
getContext().getSystemService(Context.ACTIVITY_SERVICE);
if (am != null) {
- am.removeTask(ad.persistentTaskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ am.removeTask(ad.persistentTaskId);
// Accessibility feedback
setContentDescription(
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 76e8181..be7d322 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -54,7 +54,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/** A proxy implementation for the recents component */
-public class AlternateRecentsComponent {
+public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener {
final public static String EXTRA_FROM_HOME = "recents.triggeredOverHome";
final public static String EXTRA_FROM_SEARCH_HOME = "recents.triggeredOverSearchHome";
@@ -62,7 +62,9 @@ public class AlternateRecentsComponent {
final public static String EXTRA_FROM_TASK_ID = "recents.activeTaskId";
final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "recents.triggeredFromAltTab";
final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "recents.triggeredFromHomeKey";
+ final public static String EXTRA_REUSE_TASK_STACK_VIEWS = "recents.reuseTaskStackViews";
+ final public static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
final public static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
final public static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
@@ -77,7 +79,10 @@ public class AlternateRecentsComponent {
Context mContext;
LayoutInflater mInflater;
SystemServicesProxy mSystemServicesProxy;
+ Handler mHandler;
boolean mBootCompleted;
+ boolean mStartAnimationTriggered;
+ boolean mCanReuseTaskStackViews = true;
// Task launching
RecentsConfiguration mConfig;
@@ -103,6 +108,7 @@ public class AlternateRecentsComponent {
mInflater = LayoutInflater.from(context);
mContext = context;
mSystemServicesProxy = new SystemServicesProxy(context);
+ mHandler = new Handler();
mTaskStackBounds = new Rect();
}
@@ -128,7 +134,7 @@ public class AlternateRecentsComponent {
}
// When we start, preload the metadata associated with the previous tasks
- RecentsTaskLoader.getInstance().preload(mContext);
+ RecentsTaskLoader.getInstance().preload(mContext, RecentsTaskLoader.ALL_TASKS);
}
public void onBootCompleted() {
@@ -176,7 +182,9 @@ public class AlternateRecentsComponent {
}
public void onPreloadRecents() {
- // Do nothing
+ // When we start, preload the metadata associated with the previous tasks
+ RecentsTaskLoader.getInstance().preload(mContext,
+ Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
}
public void onCancelPreloadingRecents() {
@@ -186,7 +194,7 @@ public class AlternateRecentsComponent {
void showRelativeAffiliatedTask(boolean showNextTask) {
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
- -1, -1, false, true, null, null);
+ -1, -1, RecentsTaskLoader.ALL_TASKS, false, true, null, null);
// Return early if there are no tasks
if (stack.getTaskCount() == 0) return;
@@ -251,6 +259,8 @@ public class AlternateRecentsComponent {
}
public void onConfigurationChanged(Configuration newConfig) {
+ // Don't reuse task stack views if the configuration changes
+ mCanReuseTaskStackViews = false;
// Reload the header bar layout
reloadHeaderBarLayout();
}
@@ -364,23 +374,28 @@ public class AlternateRecentsComponent {
* Creates the activity options for a unknown state->recents transition.
*/
ActivityOptions getUnknownTransitionActivityOptions() {
+ mStartAnimationTriggered = false;
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_unknown_enter,
- R.anim.recents_from_unknown_exit);
+ R.anim.recents_from_unknown_exit,
+ mHandler, this);
}
/**
* Creates the activity options for a home->recents transition.
*/
ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) {
+ mStartAnimationTriggered = false;
if (fromSearchHome) {
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_search_launcher_enter,
- R.anim.recents_from_search_launcher_exit);
+ R.anim.recents_from_search_launcher_exit,
+ mHandler, this);
}
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_launcher_enter,
- R.anim.recents_from_launcher_exit);
+ R.anim.recents_from_launcher_exit,
+ mHandler, this);
}
/**
@@ -408,9 +423,10 @@ public class AlternateRecentsComponent {
c.setBitmap(null);
}
+ mStartAnimationTriggered = false;
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
- toTaskRect.height(), null);
+ toTaskRect.height(), this);
}
// If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -423,7 +439,7 @@ public class AlternateRecentsComponent {
// Get the stack of tasks that we are animating into
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
- runningTaskId, -1, false, isTopTaskHome, null, null);
+ runningTaskId, -1, RecentsTaskLoader.ALL_TASKS, false, isTopTaskHome, null, null);
if (stack.getTaskCount() == 0) {
return null;
}
@@ -529,11 +545,13 @@ public class AlternateRecentsComponent {
}
intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, mTriggeredFromAltTab);
intent.putExtra(EXTRA_FROM_TASK_ID, (topTask != null) ? topTask.id : -1);
+ intent.putExtra(EXTRA_REUSE_TASK_STACK_VIEWS, mCanReuseTaskStackViews);
if (opts != null) {
mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
} else {
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
+ mCanReuseTaskStackViews = true;
}
/** Sets the RecentsComponent callbacks. */
@@ -547,4 +565,42 @@ public class AlternateRecentsComponent {
sRecentsComponentCallbacks.onVisibilityChanged(visible);
}
}
+
+ /**** OnAnimationStartedListener Implementation ****/
+
+ @Override
+ public void onAnimationStarted() {
+ // Notify recents to start the enter animation
+ if (!mStartAnimationTriggered) {
+ // There can be a race condition between the start animation callback and
+ // the start of the new activity (where we register the receiver that listens
+ // to this broadcast, so we add our own receiver and if that gets called, then
+ // we know the activity has not yet started and we can retry sending the broadcast.
+ BroadcastReceiver fallbackReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (getResultCode() == Activity.RESULT_OK) {
+ mStartAnimationTriggered = true;
+ return;
+ }
+
+ // Schedule for the broadcast to be sent again after some time
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ onAnimationStarted();
+ }
+ }, 25);
+ }
+ };
+
+ // Send the broadcast to notify Recents that the animation has started
+ Intent intent = new Intent(ACTION_START_ENTER_ANIMATION);
+ intent.setPackage(mContext.getPackageName());
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+ Intent.FLAG_RECEIVER_FOREGROUND);
+ mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
+ fallbackReceiver, null, Activity.RESULT_CANCELED, null, null);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d2c55f7..f8d981f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -27,6 +27,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -142,6 +143,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
} else if (action.equals(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
// If we are toggling Recents, then first unfilter any filtered stacks first
dismissRecentsToFocusedTaskOrHome(true);
+ } else if (action.equals(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION)) {
+ // Trigger the enter animation
+ onEnterAnimationTriggered();
+ // Notify the fallback receiver that we have successfully got the broadcast
+ // See AlternateRecentsComponent.onAnimationStarted()
+ setResultCode(Activity.RESULT_OK);
}
}
};
@@ -157,7 +164,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// When the screen turns off, dismiss Recents to Home
dismissRecentsToHome(false);
// Start preloading some tasks in the background
- RecentsTaskLoader.getInstance().preload(RecentsActivity.this);
+ RecentsTaskLoader.getInstance().preload(RecentsActivity.this,
+ Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
} else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
// When the search activity changes, update the Search widget
refreshSearchWidget();
@@ -188,6 +196,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
AlternateRecentsComponent.EXTRA_FROM_TASK_ID, -1);
mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
+ mConfig.launchedReuseTaskStackViews = launchIntent.getBooleanExtra(
+ AlternateRecentsComponent.EXTRA_REUSE_TASK_STACK_VIEWS, false);
// Load all the tasks
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -397,8 +407,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Update if we are getting a configuration change
if (savedInstanceState != null) {
+ // Update RecentsConfiguration
+ mConfig = RecentsConfiguration.reinitialize(this,
+ RecentsTaskLoader.getInstance().getSystemServicesProxy());
mConfig.updateOnConfigurationChange();
- onConfigurationChange();
+ // Trigger the enter animation
+ onEnterAnimationTriggered();
}
// Start listening for widget package changes if there is one bound, post it since we don't
@@ -428,19 +442,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
- /** Called when the configuration changes. */
- void onConfigurationChange() {
- // Update RecentsConfiguration
- mConfig = RecentsConfiguration.reinitialize(this,
- RecentsTaskLoader.getInstance().getSystemServicesProxy());
-
- // Try and start the enter animation (or restart it on configuration changed)
- ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
- mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
- // Animate the SystemUI scrim views
- mScrimViews.startEnterRecentsAnimation();
- }
-
/** Handles changes to the activity visibility. */
void onRecentsActivityVisibilityChanged(boolean visible) {
if (!visible) {
@@ -474,6 +475,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
IntentFilter filter = new IntentFilter();
filter.addAction(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY);
filter.addAction(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY);
+ filter.addAction(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION);
registerReceiver(mServiceBroadcastReceiver, filter);
// Register any broadcast receivers for the task loader
@@ -492,8 +494,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
protected void onStop() {
super.onStop();
- // Remove all the views
- mRecentsView.removeAllTaskStacks();
+ // Notify the views that we are no longer visible
+ mRecentsView.onRecentsHidden();
// Unregister the RecentsService receiver
unregisterReceiver(mServiceBroadcastReceiver);
@@ -515,8 +517,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
- @Override
- public void onEnterAnimationComplete() {
+ public void onEnterAnimationTriggered() {
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
@@ -584,7 +585,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
/** Called when debug mode is triggered */
public void onDebugModeTriggered() {
-
if (mConfig.developerOptionsEnabled) {
SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index bfea3f7..e0c76b1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -115,8 +115,8 @@ public class RecentsConfiguration {
public boolean launchedWithAltTab;
public boolean launchedWithNoRecentTasks;
public boolean launchedFromAppWithThumbnail;
- public boolean launchedFromAppWithScreenshot;
public boolean launchedFromHome;
+ public boolean launchedReuseTaskStackViews;
public int launchedToTaskId;
/** Misc **/
@@ -308,6 +308,7 @@ public class RecentsConfiguration {
launchedWithNoRecentTasks = false;
launchedFromAppWithThumbnail = false;
launchedFromHome = false;
+ launchedReuseTaskStackViews = false;
launchedToTaskId = -1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
index 4456066..735f79f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
@@ -82,4 +82,9 @@ public class DozeTrigger {
public boolean hasTriggered() {
return mHasTriggered;
}
+
+ /** Resets the doze trigger state. */
+ public void resetTrigger() {
+ mHasTriggered = false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 71a3ef1..b661385 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -291,18 +291,18 @@ public class SystemServicesProxy {
}
}
- /** Removes the task and kills the process */
- public void removeTask(int taskId, boolean isDocument) {
+ /** Removes the task */
+ public void removeTask(int taskId) {
if (mAm == null) return;
if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
- // Remove the task, and only kill the process if it is not a document
- mAm.removeTask(taskId, isDocument ? 0 : ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ // Remove the task.
+ mAm.removeTask(taskId);
}
/**
* Returns the activity info for a given component name.
- *
+ *
* @param cn The component name of the activity.
* @param userId The userId of the user that this is for.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index a0dee07..e1179fa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -17,7 +17,6 @@
package com.android.systemui.recents.misc;
import android.animation.Animator;
-import android.content.Intent;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
@@ -184,12 +183,6 @@ public class Utilities {
sPropertyMethod.invoke(null, property, value);
}
- /** Returns whether the specified intent is a document. */
- public static boolean isDocument(Intent intent) {
- int flags = intent.getFlags();
- return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
- }
-
/**
* Cancels an animation ensuring that if it has listeners, onCancel and onEnd
* are not called.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index b4f62d5..390507f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -260,6 +260,7 @@ public class RecentsTaskLoader {
private static final String TAG = "RecentsTaskLoader";
static RecentsTaskLoader sInstance;
+ public static final int ALL_TASKS = -1;
SystemServicesProxy mSystemServicesProxy;
DrawableLruCache mApplicationIconCache;
@@ -326,10 +327,9 @@ public class RecentsTaskLoader {
/** Gets the list of recent tasks, ordered from back to front. */
private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp,
- boolean isTopTaskHome) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
+ int numTasksToLoad, boolean isTopTaskHome) {
List<ActivityManager.RecentTaskInfo> tasks =
- ssp.getRecentTasks(config.maxNumTasksToLoad, UserHandle.CURRENT.getIdentifier(),
+ ssp.getRecentTasks(numTasksToLoad, UserHandle.CURRENT.getIdentifier(),
isTopTaskHome);
Collections.reverse(tasks);
return tasks;
@@ -416,7 +416,8 @@ public class RecentsTaskLoader {
ArrayList<Task.TaskKey> taskKeys = new ArrayList<Task.TaskKey>();
ArrayList<Task> tasksToLoad = new ArrayList<Task>();
TaskStack stack = getTaskStack(mSystemServicesProxy, context.getResources(),
- -1, preloadCount, true, isTopTaskHome, taskKeys, tasksToLoad);
+ -1, preloadCount, RecentsTaskLoader.ALL_TASKS, true, isTopTaskHome, taskKeys,
+ tasksToLoad);
SpaceNode root = new SpaceNode();
root.setStack(stack);
@@ -428,10 +429,10 @@ public class RecentsTaskLoader {
}
/** Preloads the set of recent tasks (not including thumbnails). */
- public void preload(Context context) {
+ public void preload(Context context, int numTasksToPreload) {
ArrayList<Task> tasksToLoad = new ArrayList<Task>();
getTaskStack(mSystemServicesProxy, context.getResources(),
- -1, -1, true, true, null, tasksToLoad);
+ -1, -1, numTasksToPreload, true, true, null, tasksToLoad);
// Start the task loader and add all the tasks we need to load
mLoadQueue.addTasks(tasksToLoad);
@@ -440,11 +441,13 @@ public class RecentsTaskLoader {
/** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
public synchronized TaskStack getTaskStack(SystemServicesProxy ssp, Resources res,
- int preloadTaskId, int preloadTaskCount,
+ int preloadTaskId, int preloadTaskCount, int loadTaskCount,
boolean loadTaskThumbnails, boolean isTopTaskHome,
List<Task.TaskKey> taskKeysOut, List<Task> tasksToLoadOut) {
RecentsConfiguration config = RecentsConfiguration.getInstance();
- List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, isTopTaskHome);
+ List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp,
+ (loadTaskCount == ALL_TASKS ? config.maxNumTasksToLoad : loadTaskCount),
+ isTopTaskHome);
HashMap<Task.ComponentNameKey, ActivityInfoHandle> activityInfoCache =
new HashMap<Task.ComponentNameKey, ActivityInfoHandle>();
ArrayList<Task> tasksToAdd = new ArrayList<Task>();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 6b0d306..81ee839 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -34,7 +34,6 @@ import android.widget.FrameLayout;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
@@ -96,42 +95,57 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** Set/get the bsp root node */
public void setTaskStacks(ArrayList<TaskStack> stacks) {
- // Remove all TaskStackViews (but leave the search bar)
+ int numStacks = stacks.size();
+
+ // Make a list of the stack view children only
+ ArrayList<TaskStackView> stackViews = new ArrayList<TaskStackView>();
int childCount = getChildCount();
- for (int i = childCount - 1; i >= 0; i--) {
- View v = getChildAt(i);
- if (v != mSearchBar) {
- removeViewAt(i);
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child != mSearchBar) {
+ stackViews.add((TaskStackView) child);
}
}
- // Create and add all the stacks for this partition of space.
+ // Remove all/extra stack views
+ int numTaskStacksToKeep = 0; // Keep no tasks if we are recreating the layout
+ if (mConfig.launchedReuseTaskStackViews) {
+ numTaskStacksToKeep = Math.min(childCount, numStacks);
+ }
+ for (int i = stackViews.size() - 1; i >= numTaskStacksToKeep; i--) {
+ removeView(stackViews.get(i));
+ stackViews.remove(i);
+ }
+
+ // Update the stack views that we are keeping
+ for (int i = 0; i < numTaskStacksToKeep; i++) {
+ stackViews.get(i).setStack(stacks.get(i));
+ }
+
+ // Add remaining/recreate stack views
mStacks = stacks;
- int numStacks = mStacks.size();
- for (int i = 0; i < numStacks; i++) {
- TaskStack stack = mStacks.get(i);
+ for (int i = stackViews.size(); i < numStacks; i++) {
+ TaskStack stack = stacks.get(i);
TaskStackView stackView = new TaskStackView(getContext(), stack);
stackView.setCallbacks(this);
- // Enable debug mode drawing
- if (mConfig.debugModeEnabled) {
- stackView.setDebugOverlay(mDebugOverlay);
- }
addView(stackView);
}
- // Reset the launched state
- mAlreadyLaunchingTask = false;
- }
-
- /** Removes all the task stack views from this recents view. */
- public void removeAllTaskStacks() {
- int childCount = getChildCount();
- for (int i = childCount - 1; i >= 0; i--) {
- View child = getChildAt(i);
- if (child != mSearchBar) {
- removeViewAt(i);
+ // Enable debug mode drawing on all the stacks if necessary
+ if (mConfig.debugModeEnabled) {
+ for (int i = childCount - 1; i >= 0; i--) {
+ View v = getChildAt(i);
+ if (v != mSearchBar) {
+ TaskStackView stackView = (TaskStackView) v;
+ stackView.setDebugOverlay(mDebugOverlay);
+ }
}
}
+
+ // Reset the launched state
+ mAlreadyLaunchingTask = false;
+ // Trigger a new layout
+ requestLayout();
}
/** Launches the focused task from the first stack if possible */
@@ -522,8 +536,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
loader.deleteTaskData(t, false);
// Remove the old task from activity manager
- RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id,
- Utilities.isDocument(t.key.baseIntent));
+ RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id);
}
@Override
@@ -531,6 +544,19 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
mCb.onAllTaskViewsDismissed();
}
+ /** Final callback after Recents is finally hidden. */
+ public void onRecentsHidden() {
+ // Notify each task stack view
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child != mSearchBar) {
+ TaskStackView stackView = (TaskStackView) child;
+ stackView.onRecentsHidden();
+ }
+ }
+ }
+
@Override
public void onTaskStackFilterTriggered() {
// Hide the search bar
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index dee26e6..9df0db6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -40,6 +40,7 @@ import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
/* The visual representation of a task stack view */
@@ -99,25 +100,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
};
- // A convenience runnable to return all views to the pool
- Runnable mReturnAllViewsToPoolRunnable = new Runnable() {
- @Override
- public void run() {
- int childCount = getChildCount();
- for (int i = childCount - 1; i >= 0; i--) {
- TaskView tv = (TaskView) getChildAt(i);
- mViewPool.returnViewToPool(tv);
- // Also hide the view since we don't need it anymore
- tv.setVisibility(View.INVISIBLE);
- }
- }
- };
-
public TaskStackView(Context context, TaskStack stack) {
super(context);
+ // Set the stack first
+ setStack(stack);
mConfig = RecentsConfiguration.getInstance();
- mStack = stack;
- mStack.setCallbacks(this);
mViewPool = new ViewPool<TaskView, Task>(context, this);
mInflater = LayoutInflater.from(context);
mLayoutAlgorithm = new TaskStackViewLayoutAlgorithm(mConfig);
@@ -143,11 +130,62 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mCb = cb;
}
+ /** Sets the task stack */
+ void setStack(TaskStack stack) {
+ // Unset the old stack
+ if (mStack != null) {
+ mStack.setCallbacks(null);
+
+ // Return all existing views to the pool
+ reset();
+ // Layout again with the new stack
+ requestLayout();
+ }
+
+ // Set the new stack
+ mStack = stack;
+ if (mStack != null) {
+ mStack.setCallbacks(this);
+ }
+ }
+
/** Sets the debug overlay */
public void setDebugOverlay(DebugOverlayView overlay) {
mDebugOverlay = overlay;
}
+ /** Resets this TaskStackView for reuse. */
+ void reset() {
+ // Return all the views to the pool
+ int childCount = getChildCount();
+ for (int i = childCount - 1; i >= 0; i--) {
+ TaskView tv = (TaskView) getChildAt(i);
+ mViewPool.returnViewToPool(tv);
+ }
+
+ // Mark each task view for relayout
+ if (mViewPool != null) {
+ Iterator<TaskView> iter = mViewPool.poolViewIterator();
+ if (iter != null) {
+ while (iter.hasNext()) {
+ TaskView tv = iter.next();
+ tv.reset();
+ }
+ }
+ }
+
+ // Reset the stack state
+ resetFocusedTask();
+ mStackViewsDirty = true;
+ mStackViewsClipDirty = true;
+ mAwaitingFirstLayout = true;
+ mPrevAccessibilityFocusedIndex = -1;
+ if (mUIDozeTrigger != null) {
+ mUIDozeTrigger.stopDozing();
+ mUIDozeTrigger.resetTrigger();
+ }
+ }
+
/** Requests that the views be synchronized with the model */
void requestSynchronizeStackViewsWithModel() {
requestSynchronizeStackViewsWithModel(0);
@@ -510,6 +548,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
tv.dismissTask();
}
+ /** Resets the focused task. */
+ void resetFocusedTask() {
+ if (mFocusedTaskIndex > -1) {
+ Task t = mStack.getTasks().get(mFocusedTaskIndex);
+ TaskView tv = getChildViewForTask(t);
+ tv.unsetFocusedTask();
+ }
+ mFocusedTaskIndex = -1;
+ }
+
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
@@ -543,6 +591,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
@Override
public void computeScroll() {
+ if (mStack == null) return;
+
mStackScroller.computeScroll();
// Synchronize the views
synchronizeStackViewsWithModel();
@@ -758,9 +808,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView tv = (TaskView) getChildAt(i);
tv.startExitToHomeAnimation(ctx);
}
-
- // Add a runnable to the post animation ref counter to clear all the views
- ctx.postAnimationTrigger.addLastDecrementRunnable(mReturnAllViewsToPoolRunnable);
}
/** Animates a task view in this stack as it launches. */
@@ -780,6 +827,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
+ /** Final callback after Recents is finally hidden. */
+ void onRecentsHidden() {
+ reset();
+ setStack(null);
+ }
+
public boolean isTransformedTouchPointInView(float x, float y, View child) {
return isTransformedTouchPointInView(x, y, child, null);
}
@@ -944,20 +997,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Reset the view properties
tv.resetViewProperties();
+
+ // Reset the clip state of the task view
+ tv.setClipViewInStack(false);
}
@Override
public void prepareViewToLeavePool(TaskView tv, Task task, boolean isNewView) {
+ // It is possible for a view to be returned to the view pool before it is laid out,
+ // which means that we will need to relayout the view when it is first used next.
+ boolean requiresRelayout = tv.getWidth() <= 0 && !isNewView;
+
// Rebind the task and request that this task's data be filled into the TaskView
tv.onTaskBound(task);
// Load the task data
RecentsTaskLoader.getInstance().loadTaskData(task);
- // Sanity check, the task view should always be clipping against the stack at this point,
- // but just in case, re-enable it here
- tv.setClipViewInStack(true);
-
// If the doze trigger has already fired, then update the state for this task view
if (mUIDozeTrigger.hasTriggered()) {
tv.setNoUserInteractionState();
@@ -985,13 +1041,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Add/attach the view to the hierarchy
if (isNewView) {
addView(tv, insertIndex);
-
- // Set the callbacks and listeners for this new view
- tv.setTouchEnabled(true);
- tv.setCallbacks(this);
} else {
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
+ if (requiresRelayout) {
+ tv.requestLayout();
+ }
}
+
+ // Set the new state for this view, including the callbacks and view clipping
+ tv.setCallbacks(this);
+ tv.setTouchEnabled(true);
+ tv.setClipViewInStack(true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 7b4e10a..790130a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -112,6 +112,14 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mCb = cb;
}
+ /** Resets this TaskView for reuse. */
+ void reset() {
+ resetViewProperties();
+ resetNoUserInteractionState();
+ setClipViewInStack(false);
+ setCallbacks(null);
+ }
+
/** Gets the task */
Task getTask() {
return mTask;
@@ -191,6 +199,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Resets this view's properties */
void resetViewProperties() {
setDim(0);
+ setLayerType(View.LAYER_TYPE_NONE, null);
TaskViewTransform.reset(this);
}
@@ -448,6 +457,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mHeaderView.setNoUserInteractionState();
}
+ /** Resets the state tracking that the user has not interacted with the stack after a certain time. */
+ void resetNoUserInteractionState() {
+ mHeaderView.resetNoUserInteractionState();
+ }
+
/** Dismisses this task. */
void dismissTask() {
// Animate out the view and call the callback
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index ba868f5..5de84bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -263,6 +263,11 @@ public class TaskViewHeader extends FrameLayout {
}
}
+ /** Resets the state tracking that the user has not interacted with the stack after a certain time. */
+ void resetNoUserInteractionState() {
+ mDismissButton.setVisibility(View.INVISIBLE);
+ }
+
@Override
protected int[] onCreateDrawableState(int extraSpace) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
index af0094e..12b91af 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
@@ -75,4 +75,12 @@ public class ViewPool<V, T> {
mViewCreator.prepareViewToLeavePool(v, prepareData, isNewView);
return v;
}
+
+ /** Returns an iterator to the list of the views in the pool. */
+ Iterator<V> poolViewIterator() {
+ if (mPool != null) {
+ return mPool.iterator();
+ }
+ return null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 7bbf9e2..725a1a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -59,7 +59,6 @@ import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
-import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.Display;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
index 628aab8..7ae6764 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
@@ -17,10 +17,11 @@
package com.android.systemui.statusbar;
import android.app.StatusBarManager;
+import android.content.res.Resources;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
+import com.android.systemui.R;
public class DelegateViewHelper {
private View mDelegateView;
@@ -106,8 +107,8 @@ public class DelegateViewHelper {
public void setSourceView(View view) {
mSourceView = view;
if (mSourceView != null) {
- mTriggerThreshhold =
- ViewConfiguration.get(mSourceView.getContext()).getScaledPagingTouchSlop();
+ Resources r = mSourceView.getContext().getResources();
+ mTriggerThreshhold = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java
index d55b0b3..35fd688 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java
@@ -61,4 +61,9 @@ public class DismissViewImageButton extends ImageButton {
outRect.top += translationY;
outRect.bottom += translationY;
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index a4e5e74..f8332ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -22,6 +22,7 @@ import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewStub;
import android.view.accessibility.AccessibilityEvent;
@@ -68,6 +69,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
private NotificationGuts mGuts;
private StatusBarNotification mStatusBarNotification;
+ private boolean mIsHeadsUp;
public void setIconAnimationRunning(boolean running) {
setIconAnimationRunning(running, mPublicLayout);
@@ -122,6 +124,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
return mStatusBarNotification;
}
+ public void setHeadsUp(boolean isHeadsUp) {
+ mIsHeadsUp = isHeadsUp;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
@@ -147,14 +153,16 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
mShowingPublicInitialized = false;
mIsSystemExpanded = false;
mExpansionDisabled = false;
- mPublicLayout.reset();
- mPrivateLayout.reset();
+ mPublicLayout.reset(mIsHeadsUp);
+ mPrivateLayout.reset(mIsHeadsUp);
resetHeight();
logExpansionEvent(false, wasExpanded);
}
public void resetHeight() {
- super.resetHeight();
+ if (mIsHeadsUp) {
+ resetActualHeight();
+ }
mMaxExpandHeight = 0;
mWasReset = true;
onHeightReset();
@@ -162,6 +170,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
}
@Override
+ protected boolean filterMotionEvent(MotionEvent event) {
+ return mIsHeadsUp || super.filterMotionEvent(event);
+ }
+
+ @Override
protected void onFinishInflate() {
super.onFinishInflate();
mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index edfbe86..bf1e78e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -103,9 +103,13 @@ public abstract class ExpandableView extends FrameLayout {
}
}
- protected void resetHeight() {
+ /**
+ * Resets the height of the view on the next layout pass
+ */
+ protected void resetActualHeight() {
mActualHeight = 0;
mActualHeightInitialized = false;
+ requestLayout();
}
protected int getInitialHeight() {
@@ -120,7 +124,7 @@ public abstract class ExpandableView extends FrameLayout {
return false;
}
- private boolean filterMotionEvent(MotionEvent event) {
+ protected boolean filterMotionEvent(MotionEvent event) {
return event.getActionMasked() != MotionEvent.ACTION_DOWN
|| event.getY() > mClipTopAmount && event.getY() < mActualHeight;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index ce35e4b..58067c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -146,8 +146,8 @@ public class KeyguardIndicationController {
try {
long chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining();
if (chargingTimeRemaining > 0) {
- String chargingTimeFormatted =
- Formatter.formatShortElapsedTime(mContext, chargingTimeRemaining);
+ String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
+ mContext, chargingTimeRemaining);
return mContext.getResources().getString(
R.string.keyguard_indication_charging_time, chargingTimeFormatted);
}
@@ -162,8 +162,9 @@ public class KeyguardIndicationController {
KeyguardUpdateMonitorCallback mUpdateMonitor = new KeyguardUpdateMonitorCallback() {
@Override
public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
- mPowerPluggedIn = status.status == BatteryManager.BATTERY_STATUS_CHARGING
+ boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
|| status.status == BatteryManager.BATTERY_STATUS_FULL;
+ mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
mPowerCharged = status.isCharged();
updateIndication();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 9b11f9b..99214a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -74,7 +74,7 @@ public class NotificationContentView extends FrameLayout {
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
- reset();
+ reset(true);
}
@Override
@@ -89,7 +89,7 @@ public class NotificationContentView extends FrameLayout {
updateVisibility();
}
- public void reset() {
+ public void reset(boolean resetActualHeight) {
if (mContractedChild != null) {
mContractedChild.animate().cancel();
}
@@ -100,8 +100,10 @@ public class NotificationContentView extends FrameLayout {
mContractedChild = null;
mExpandedChild = null;
mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
- mActualHeight = mSmallHeight;
mContractedVisible = true;
+ if (resetActualHeight) {
+ mActualHeight = mSmallHeight;
+ }
}
public View getContractedChild() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 32fb567..e89e15d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -45,6 +45,7 @@ public class BarTransitions {
public static final int MODE_LIGHTS_OUT = 3;
public static final int MODE_TRANSPARENT = 4;
public static final int MODE_WARNING = 5;
+ public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6;
public static final int LIGHTS_IN_DURATION = 250;
public static final int LIGHTS_OUT_DURATION = 750;
@@ -75,6 +76,9 @@ public class BarTransitions {
|| mode == MODE_TRANSPARENT)) {
mode = MODE_OPAQUE;
}
+ if (!HIGH_END && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) {
+ mode = MODE_LIGHTS_OUT;
+ }
if (mMode == mode) return;
int oldMode = mMode;
mMode = mode;
@@ -102,6 +106,7 @@ public class BarTransitions {
if (mode == MODE_LIGHTS_OUT) return "MODE_LIGHTS_OUT";
if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT";
if (mode == MODE_WARNING) return "MODE_WARNING";
+ if (mode == MODE_LIGHTS_OUT_TRANSPARENT) return "MODE_LIGHTS_OUT_TRANSPARENT";
throw new IllegalArgumentException("Unknown mode " + mode);
}
@@ -109,6 +114,10 @@ public class BarTransitions {
mBarBackground.finishAnimation();
}
+ protected boolean isLightsOut(int mode) {
+ return mode == MODE_LIGHTS_OUT || mode == MODE_LIGHTS_OUT_TRANSPARENT;
+ }
+
private static class BarBackgroundDrawable extends Drawable {
private final int mOpaque;
private final int mSemiTransparent;
@@ -196,7 +205,7 @@ public class BarTransitions {
targetColor = mSemiTransparent;
} else if (mMode == MODE_SEMI_TRANSPARENT) {
targetColor = mSemiTransparent;
- } else if (mMode == MODE_TRANSPARENT) {
+ } else if (mMode == MODE_TRANSPARENT || mMode == MODE_LIGHTS_OUT_TRANSPARENT) {
targetColor = mTransparent;
} else {
targetColor = mOpaque;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 052b6c6..15f6dc2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -84,7 +84,7 @@ public final class NavigationBarTransitions extends BarTransitions {
applyBackButtonQuiescentAlpha(mode, animate);
// apply to lights out
- applyLightsOut(mode == MODE_LIGHTS_OUT, animate, force);
+ applyLightsOut(isLightsOut(mode), animate, force);
}
private float alphaForMode(int mode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 9bb52e7..1e4dfb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -21,6 +21,7 @@ import android.animation.LayoutTransition.TransitionListener;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
+import android.app.ActivityManagerNative;
import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Configuration;
@@ -30,6 +31,7 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
@@ -43,6 +45,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.DelegateViewHelper;
@@ -332,7 +335,7 @@ public class NavigationBarView extends LinearLayout {
mDisabledFlags = disabledFlags;
final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
- final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
+ boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
&& ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
final boolean disableSearch = ((disabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0);
@@ -357,6 +360,11 @@ public class NavigationBarView extends LinearLayout {
}
}
}
+ if (inLockTask() && disableRecent && !disableHome) {
+ // Don't hide recents when in lock task, it is used for exiting.
+ // Unless home is hidden, then in DPM locked mode and no exit available.
+ disableRecent = false;
+ }
getBackButton() .setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
getHomeButton() .setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
@@ -365,6 +373,14 @@ public class NavigationBarView extends LinearLayout {
mBarTransitions.applyBackButtonQuiescentAlpha(mBarTransitions.getMode(), true /*animate*/);
}
+ private boolean inLockTask() {
+ try {
+ return ActivityManagerNative.getDefault().isInLockTaskMode();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
private void setVisibleOrGone(View view, boolean visible) {
if (view != null) {
view.setVisibility(visible ? VISIBLE : GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
index c253e19..fdfcdfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
@@ -17,9 +17,11 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.content.res.Resources;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
+import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
public class NavigationBarViewTaskSwitchHelper extends GestureDetector.SimpleOnGestureListener {
@@ -36,7 +38,8 @@ public class NavigationBarViewTaskSwitchHelper extends GestureDetector.SimpleOnG
public NavigationBarViewTaskSwitchHelper(Context context) {
ViewConfiguration configuration = ViewConfiguration.get(context);
- mScrollTouchSlop = 4 * configuration.getScaledTouchSlop();
+ Resources r = context.getResources();
+ mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
mTaskSwitcherDetector = new GestureDetector(context, this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index d9e44c3..bb992b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -291,8 +291,8 @@ public class NotificationPanelView extends PanelView implements
} else {
setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
mNotificationStackScroller.setStackHeight(getExpandedHeight());
- updateHeader();
}
+ updateHeader();
mNotificationStackScroller.updateIsSmallScreen(
mHeader.getCollapsedHeight() + mQsPeekHeight);
}
@@ -1329,6 +1329,16 @@ public class NotificationPanelView extends PanelView implements
float notificationHeight = mNotificationStackScroller.getHeight()
- mNotificationStackScroller.getEmptyBottomMargin()
- mNotificationStackScroller.getTopPadding();
+
+ // When only empty shade view is visible in QS collapsed state, simulate that we would have
+ // it in expanded QS state as well so we don't run into troubles when fading the view in/out
+ // and expanding/collapsing the whole panel from/to quick settings.
+ if (mNotificationStackScroller.getNotGoneChildCount() == 0
+ && mShadeEmpty) {
+ notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight()
+ + mNotificationStackScroller.getBottomStackPeekSize()
+ + mNotificationStackScroller.getCollapseSecondCardPadding();
+ }
float totalHeight = Math.max(
mQsMaxExpansionHeight + mNotificationStackScroller.getNotificationTopPadding(),
mClockPositionResult.stackScrollerPadding - mTopPaddingAdjustment)
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 fc7081b..5928845 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -23,6 +23,7 @@ import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
@@ -2600,8 +2601,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
private int barMode(int vis, int transientFlag, int translucentFlag) {
+ int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_TRANSPARENT;
return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT
: (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT
+ : (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT
: (vis & View.SYSTEM_UI_TRANSPARENT) != 0 ? MODE_TRANSPARENT
: (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT
: MODE_OPAQUE;
@@ -3071,8 +3074,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
else if (Intent.ACTION_SCREEN_ON.equals(action)) {
mScreenOn = true;
- // work around problem where mDisplay.getRotation() is not stable while screen is off (bug 7086018)
- repositionNavigationBar();
notifyNavigationBarScreenOn(true);
}
else if (ACTION_DEMO.equals(action)) {
@@ -3597,6 +3598,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
instantCollapseNotificationPanel();
}
updateKeyguardState(staying, false /* fromShadeLocked */);
+
+ // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
+ // visibilities so next time we open the panel we know the correct height already.
+ if (mQSPanel != null) {
+ mQSPanel.refreshAllTiles();
+ }
return staying;
}
@@ -3630,9 +3637,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
private void updatePublicMode() {
- setLockscreenPublicMode(
- (mStatusBarKeyguardViewManager.isShowing() ||
- mStatusBarKeyguardViewManager.isOccluded())
+ setLockscreenPublicMode(mStatusBarKeyguardViewManager.isShowing()
&& mStatusBarKeyguardViewManager.isSecure());
}
@@ -3963,6 +3968,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// long-pressed 'together'
if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
activityManager.stopLockTaskModeOnCurrent();
+ // When exiting refresh disabled flags.
+ mNavigationBarView.setDisabledFlags(mDisabled, true);
} else if ((v.getId() == R.id.back)
&& !mNavigationBarView.getRecentsButton().isPressed()) {
// If we aren't pressing recents right now then they presses
@@ -3978,6 +3985,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// When in accessibility mode a long press that is recents (not back)
// should stop lock task.
activityManager.stopLockTaskModeOnCurrent();
+ // When exiting refresh disabled flags.
+ mNavigationBarView.setDisabledFlags(mDisabled, true);
}
}
if (sendBackLongPress) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
index 8520f40..fb1addf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
@@ -57,19 +57,19 @@ public final class PhoneStatusBarTransitions extends BarTransitions {
}
private float getNonBatteryClockAlphaFor(int mode) {
- return mode == MODE_LIGHTS_OUT ? ICON_ALPHA_WHEN_LIGHTS_OUT_NON_BATTERY_CLOCK
+ return isLightsOut(mode) ? ICON_ALPHA_WHEN_LIGHTS_OUT_NON_BATTERY_CLOCK
: !isOpaque(mode) ? ICON_ALPHA_WHEN_NOT_OPAQUE
: mIconAlphaWhenOpaque;
}
private float getBatteryClockAlpha(int mode) {
- return mode == MODE_LIGHTS_OUT ? ICON_ALPHA_WHEN_LIGHTS_OUT_BATTERY_CLOCK
+ return isLightsOut(mode) ? ICON_ALPHA_WHEN_LIGHTS_OUT_BATTERY_CLOCK
: getNonBatteryClockAlphaFor(mode);
}
private boolean isOpaque(int mode) {
return !(mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT
- || mode == MODE_TRANSPARENT);
+ || mode == MODE_TRANSPARENT || mode == MODE_LIGHTS_OUT_TRANSPARENT);
}
@Override
@@ -94,7 +94,7 @@ public final class PhoneStatusBarTransitions extends BarTransitions {
animateTransitionTo(mBattery, newAlphaBC),
animateTransitionTo(mClock, newAlphaBC)
);
- if (mode == MODE_LIGHTS_OUT) {
+ if (isLightsOut(mode)) {
anims.setDuration(LIGHTS_OUT_DURATION);
}
anims.start();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index a4db46a..45a1386 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -21,6 +21,7 @@ import android.content.Intent;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.Uri;
+import android.os.Process;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -108,7 +109,8 @@ public class QSTileHost implements QSTile.Host {
mKeyguard = keyguard;
mSecurity = security;
- final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName());
+ final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
+ Process.THREAD_PRIORITY_BACKGROUND);
ht.start();
mLooper = ht.getLooper();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 84216a4..11ff272 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -54,7 +54,6 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
private EdgeSwipeHelper mEdgeSwipeHelper;
private PhoneStatusBar mBar;
- private ExpandHelper mExpandHelper;
private long mStartTouchTime;
private ViewGroup mContentHolder;
@@ -102,6 +101,7 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
if (mHeadsUp != null) {
mHeadsUp.row.setSystemExpanded(true);
mHeadsUp.row.setSensitive(false);
+ mHeadsUp.row.setHeadsUp(true);
mHeadsUp.row.setHideSensitive(
false, false /* animated */, 0 /* delay */, 0 /* duration */);
if (mContentHolder == null) {
@@ -205,7 +205,6 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height);
- mExpandHelper = new ExpandHelper(getContext(), this, minHeight, maxHeight);
mContentHolder = (ViewGroup) findViewById(R.id.content_holder);
mContentHolder.setOutlineProvider(CONTENT_HOLDER_OUTLINE_PROVIDER);
@@ -226,7 +225,6 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
}
return mEdgeSwipeHelper.onInterceptTouchEvent(ev)
|| mSwipeHelper.onInterceptTouchEvent(ev)
- || mExpandHelper.onInterceptTouchEvent(ev)
|| super.onInterceptTouchEvent(ev);
}
@@ -254,7 +252,6 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
mBar.resetHeadsUpDecayTimer();
return mEdgeSwipeHelper.onTouchEvent(ev)
|| mSwipeHelper.onTouchEvent(ev)
- || mExpandHelper.onTouchEvent(ev)
|| super.onTouchEvent(ev);
}
@@ -399,15 +396,12 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
final float dY = ev.getY() - mFirstY;
final float daX = Math.abs(ev.getX() - mFirstX);
final float daY = Math.abs(dY);
- if (!mConsuming && (4f * daX) < daY && daY > mTouchSlop) {
+ if (!mConsuming && daX < daY && daY > mTouchSlop) {
+ releaseAndClose();
if (dY > 0) {
if (DEBUG_EDGE_SWIPE) Log.d(TAG, "found an open");
mBar.animateExpandNotificationsPanel();
}
- if (dY < 0) {
- if (DEBUG_EDGE_SWIPE) Log.d(TAG, "found a close");
- mBar.onHeadsUpDismissed();
- }
mConsuming = true;
}
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 87ce565..d543cff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2272,6 +2272,10 @@ public class NotificationStackScrollLayout extends ViewGroup
return height;
}
+ public int getEmptyShadeViewHeight() {
+ return mEmptyShadeView.getHeight();
+ }
+
public float getBottomMostNotificationBottom() {
final int count = getChildCount();
float max = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index c840f17..28ecbf9 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -69,6 +69,7 @@ public class ZenModePanel extends LinearLayout {
private static final int TIME_CONDITION_INDEX = 1;
private static final int FIRST_CONDITION_INDEX = 2;
private static final float SILENT_HINT_PULSE_SCALE = 1.1f;
+ private static final long SELECT_DEFAULT_DELAY = 300;
public static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
@@ -373,8 +374,9 @@ public class ZenModePanel extends LinearLayout {
if (isDowntime(mSessionExitCondition) && !foundDowntime) {
bind(mSessionExitCondition, null);
}
- // ensure something is selected
- checkForDefault();
+ // ensure something is selected, after waiting for providers to respond
+ mHandler.removeMessages(H.SELECT_DEFAULT);
+ mHandler.sendEmptyMessageDelayed(H.SELECT_DEFAULT, SELECT_DEFAULT_DELAY);
}
private static boolean isDowntime(Condition c) {
@@ -385,7 +387,8 @@ public class ZenModePanel extends LinearLayout {
return (ConditionTag) mZenConditions.getChildAt(index).getTag();
}
- private void checkForDefault() {
+ private void handleSelectDefault() {
+ if (!mExpanded) return;
// are we left without anything selected? if so, set a default
for (int i = 0; i < mZenConditions.getChildCount(); i++) {
if (getConditionTagAt(i).rb.isChecked()) {
@@ -638,6 +641,7 @@ public class ZenModePanel extends LinearLayout {
private static final int UPDATE_CONDITIONS = 1;
private static final int EXIT_CONDITION_CHANGED = 2;
private static final int UPDATE_ZEN = 3;
+ private static final int SELECT_DEFAULT = 4;
private H() {
super(Looper.getMainLooper());
@@ -651,6 +655,8 @@ public class ZenModePanel extends LinearLayout {
handleExitConditionChanged((Condition) msg.obj);
} else if (msg.what == UPDATE_ZEN) {
handleUpdateZen(msg.arg1);
+ } else if (msg.what == SELECT_DEFAULT) {
+ handleSelectDefault();
}
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index bf5cdff..3c44e87 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -48,6 +48,7 @@ import android.media.Ringtone;
import android.media.RingtoneManager;
import android.media.session.MediaSessionLegacyHelper;
import android.os.Bundle;
+import android.os.Debug;
import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
@@ -116,6 +117,7 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
+import java.util.List;
import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
@@ -527,6 +529,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private boolean mAllowTheaterModeWakeFromLidSwitch;
private boolean mAllowTheaterModeWakeFromWakeGesture;
+ // Whether to go to sleep entering theater mode from power button
+ private boolean mGoToSleepOnButtonPressTheaterMode;
+
// Screenshot trigger states
// Time to volume and power must be pressed within this interval of each other.
private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
@@ -984,7 +989,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Slog.i(TAG, "Toggling theater mode on.");
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 1);
- if (interactive) {
+
+ if (mGoToSleepOnButtonPressTheaterMode && interactive) {
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
}
@@ -1236,6 +1242,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
+ mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
+
mShortPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shortPressOnPowerBehavior);
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
@@ -2099,11 +2108,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
public void removeStartingWindow(IBinder appToken, View window) {
- if (DEBUG_STARTING_WINDOW) {
- RuntimeException e = new RuntimeException("here");
- e.fillInStackTrace();
- Log.v(TAG, "Removing starting window for " + appToken + ": " + window, e);
- }
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
+ + window + " Callers=" + Debug.getCallers(4));
if (window != null) {
WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
@@ -2299,24 +2305,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean goingToNotificationShade) {
if (goingToNotificationShade) {
return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
- } else if (onWallpaper) {
- Animation a = AnimationUtils.loadAnimation(mContext,
- R.anim.lock_screen_behind_enter_wallpaper);
- AnimationSet set = (AnimationSet) a;
-
- // TODO: Use XML interpolators when we have log interpolators available in XML.
- set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator);
- set.getAnimations().get(1).setInterpolator(mLogDecelerateInterpolator);
- return set;
- } else {
- Animation a = AnimationUtils.loadAnimation(mContext,
+ }
+
+ AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
+ R.anim.lock_screen_behind_enter_wallpaper :
R.anim.lock_screen_behind_enter);
- AnimationSet set = (AnimationSet) a;
- // TODO: Use XML interpolators when we have log interpolators available in XML.
- set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator);
- return set;
+ // TODO: Use XML interpolators when we have log interpolators available in XML.
+ final List<Animation> animations = set.getAnimations();
+ for (int i = animations.size() - 1; i >= 0; --i) {
+ animations.get(i).setInterpolator(mLogDecelerateInterpolator);
}
+
+ return set;
}
@@ -4767,18 +4768,39 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
if ((policyFlags & FLAG_WAKE) != 0) {
- wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion);
- return 0;
+ if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion)) {
+ return 0;
+ }
}
+
if (shouldDispatchInputWhenNonInteractive()) {
return ACTION_PASS_TO_USER;
}
+
return 0;
}
private boolean shouldDispatchInputWhenNonInteractive() {
- return keyguardIsShowingTq() && mDisplay != null &&
- mDisplay.getState() != Display.STATE_OFF;
+ // Send events to keyguard while the screen is on.
+ if (keyguardIsShowingTq() && mDisplay != null && mDisplay.getState() != Display.STATE_OFF) {
+ return true;
+ }
+
+ // Send events to a dozing dream even if the screen is off since the dream
+ // is in control of the state of the screen.
+ IDreamManager dreamManager = getDreamManager();
+
+ try {
+ if (dreamManager != null && dreamManager.isDreaming()) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException when checking if dreaming", e);
+ }
+
+ // Otherwise, consume events since the user can't see what is being
+ // interacted with.
+ return false;
}
void dispatchMediaKeyWithWakeLock(KeyEvent event) {
@@ -4949,12 +4971,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey);
}
- private void wakeUp(long wakeTime, boolean wakeInTheaterMode) {
+ private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) {
if (!wakeInTheaterMode && isTheaterModeEnabled()) {
- return;
+ return false;
}
mPowerManager.wakeUp(wakeTime);
+ return true;
}
// Called on the PowerManager's Notifier thread.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 74fef02..5997680 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -185,7 +185,8 @@ import javax.net.ssl.SSLSession;
/**
* @hide
*/
-public class ConnectivityService extends IConnectivityManager.Stub {
+public class ConnectivityService extends IConnectivityManager.Stub
+ implements PendingIntent.OnFinished {
private static final String TAG = "ConnectivityService";
private static final boolean DBG = true;
@@ -383,6 +384,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
private static final int EVENT_SYSTEM_READY = 25;
+ /**
+ * used to add a network request with a pending intent
+ * includes a NetworkRequestInfo
+ */
+ private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
+
+ /**
+ * used to remove a pending intent and its associated network request.
+ * arg1 = UID of caller
+ * obj = PendingIntent
+ */
+ private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;
+
/** Handler used for internal events. */
final private InternalHandler mHandler;
@@ -396,6 +410,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private String mNetTransitionWakeLockCausedBy = "";
private int mNetTransitionWakeLockSerialNumber;
private int mNetTransitionWakeLockTimeout;
+ private final PowerManager.WakeLock mPendingIntentWakeLock;
private InetAddress mDefaultDns;
@@ -650,6 +665,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
com.android.internal.R.integer.config_networkTransitionTimeout);
+ mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mNetTrackers = new NetworkStateTracker[
ConnectivityManager.MAX_NETWORK_TYPE+1];
@@ -2141,11 +2157,40 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
+ // If this method proves to be too slow then we can maintain a separate
+ // pendingIntent => NetworkRequestInfo map.
+ // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
+ private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) {
+ Intent intent = pendingIntent.getIntent();
+ for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
+ PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
+ if (existingPendingIntent != null &&
+ existingPendingIntent.getIntent().filterEquals(intent)) {
+ return entry.getValue();
+ }
+ }
+ return null;
+ }
+
+ private void handleRegisterNetworkRequestWithIntent(Message msg) {
+ final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
+
+ NetworkRequestInfo existingRequest = findExistingNetworkRequestInfo(nri.mPendingIntent);
+ if (existingRequest != null) { // remove the existing request.
+ if (DBG) log("Replacing " + existingRequest.request + " with "
+ + nri.request + " because their intents matched.");
+ handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
+ }
+ handleRegisterNetworkRequest(msg);
+ }
+
private void handleRegisterNetworkRequest(Message msg) {
final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
final NetworkCapabilities newCap = nri.request.networkCapabilities;
int score = 0;
+ mNetworkRequests.put(nri.request, nri);
+
// Check for the best currently alive network that satisfies this request
NetworkAgentInfo bestNetwork = null;
for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
@@ -2183,7 +2228,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mLegacyTypeTracker.add(nri.request.legacyType, bestNetwork);
}
}
- mNetworkRequests.put(nri.request, nri);
+
if (nri.isRequest) {
if (DBG) log("sending new NetworkRequest to factories");
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
@@ -2193,6 +2238,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
+ private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent,
+ int callingUid) {
+ NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
+ if (nri != null) {
+ handleReleaseNetworkRequest(nri.request, callingUid);
+ }
+ }
+
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
NetworkRequestInfo nri = mNetworkRequests.get(request);
if (nri != null) {
@@ -2228,11 +2281,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
- // Maintain the illusion. When this request arrived, we might have preteneded
+ // Maintain the illusion. When this request arrived, we might have pretended
// that a network connected to serve it, even though the network was already
// connected. Now that this request has gone away, we might have to pretend
// that the network disconnected. LegacyTypeTracker will generate that
- // phatom disconnect for this type.
+ // phantom disconnect for this type.
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
if (nai != null) {
mNetworkForRequestId.remove(nri.request.requestId);
@@ -2263,7 +2316,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
@Override
public void handleMessage(Message msg) {
- NetworkInfo info;
switch (msg.what) {
case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK:
case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
@@ -2344,6 +2396,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
handleRegisterNetworkRequest(msg);
break;
}
+ case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: {
+ handleRegisterNetworkRequestWithIntent(msg);
+ break;
+ }
+ case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
+ handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
+ break;
+ }
case EVENT_RELEASE_NETWORK_REQUEST: {
handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
break;
@@ -3357,12 +3417,23 @@ public class ConnectivityService extends IConnectivityManager.Stub {
static final boolean LISTEN = false;
final NetworkRequest request;
- IBinder mBinder;
+ final PendingIntent mPendingIntent;
+ private final IBinder mBinder;
final int mPid;
final int mUid;
final Messenger messenger;
final boolean isRequest;
+ NetworkRequestInfo(NetworkRequest r, PendingIntent pi, boolean isRequest) {
+ request = r;
+ mPendingIntent = pi;
+ messenger = null;
+ mBinder = null;
+ mPid = getCallingPid();
+ mUid = getCallingUid();
+ this.isRequest = isRequest;
+ }
+
NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, boolean isRequest) {
super();
messenger = m;
@@ -3371,6 +3442,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mPid = getCallingPid();
mUid = getCallingUid();
this.isRequest = isRequest;
+ mPendingIntent = null;
try {
mBinder.linkToDeath(this, 0);
@@ -3380,7 +3452,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
void unlinkDeathRecipient() {
- mBinder.unlinkToDeath(this, 0);
+ if (mBinder != null) {
+ mBinder.unlinkToDeath(this, 0);
+ }
}
public void binderDied() {
@@ -3391,22 +3465,46 @@ public class ConnectivityService extends IConnectivityManager.Stub {
public String toString() {
return (isRequest ? "Request" : "Listen") + " from uid/pid:" + mUid + "/" +
- mPid + " for " + request;
+ mPid + " for " + request +
+ (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
}
}
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
+ networkCapabilities = new NetworkCapabilities(networkCapabilities);
+ enforceNetworkRequestPermissions(networkCapabilities);
+ enforceMeteredApnPolicy(networkCapabilities);
+
+ if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) {
+ throw new IllegalArgumentException("Bad timeout specified");
+ }
+
+ NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
+ nextNetworkRequestId());
+ if (DBG) log("requestNetwork for " + networkRequest);
+ NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
+ NetworkRequestInfo.REQUEST);
+
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
+ if (timeoutMs > 0) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
+ nri), timeoutMs);
+ }
+ return networkRequest;
+ }
+
+ private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) {
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
== false) {
enforceConnectivityInternalPermission();
} else {
enforceChangePermission();
}
+ }
- networkCapabilities = new NetworkCapabilities(networkCapabilities);
-
+ private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
// if UID is restricted, don't allow them to bring up metered APNs
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
== false) {
@@ -3421,29 +3519,30 @@ public class ConnectivityService extends IConnectivityManager.Stub {
networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
}
}
+ }
- if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) {
- throw new IllegalArgumentException("Bad timeout specified");
- }
- NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
+ @Override
+ public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
+ PendingIntent operation) {
+ checkNotNull(operation, "PendingIntent cannot be null.");
+ networkCapabilities = new NetworkCapabilities(networkCapabilities);
+ enforceNetworkRequestPermissions(networkCapabilities);
+ enforceMeteredApnPolicy(networkCapabilities);
+
+ NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
nextNetworkRequestId());
- if (DBG) log("requestNetwork for " + networkRequest);
- NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
+ if (DBG) log("pendingRequest for " + networkRequest + " to trigger " + operation);
+ NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation,
NetworkRequestInfo.REQUEST);
-
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
- if (timeoutMs > 0) {
- mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
- nri), timeoutMs);
- }
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT,
+ nri));
return networkRequest;
}
@Override
- public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
- PendingIntent operation) {
- // TODO
- return null;
+ public void releasePendingNetworkRequest(PendingIntent operation) {
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
+ getCallingUid(), 0, operation));
}
@Override
@@ -3711,12 +3810,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private void updateCapabilities(NetworkAgentInfo networkAgent,
NetworkCapabilities networkCapabilities) {
- // TODO - turn this on in MR1 when we have more dogfooding time.
- // rematchAllNetworksAndRequests();
if (!Objects.equals(networkAgent.networkCapabilities, networkCapabilities)) {
synchronized (networkAgent) {
networkAgent.networkCapabilities = networkCapabilities;
}
+ rematchAllNetworksAndRequests(networkAgent, networkAgent.getCurrentScore());
notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
}
@@ -3738,6 +3836,39 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
+ private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent,
+ int notificationType) {
+ if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE) {
+ Intent intent = new Intent();
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK, nri.request);
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK_REQUEST,
+ networkAgent.network);
+ sendIntent(nri.mPendingIntent, intent);
+ }
+ // else not handled
+ }
+
+ private void sendIntent(PendingIntent pendingIntent, Intent intent) {
+ mPendingIntentWakeLock.acquire();
+ try {
+ if (DBG) log("Sending " + pendingIntent);
+ pendingIntent.send(mContext, 0, intent, this /* onFinished */, null /* Handler */);
+ } catch (PendingIntent.CanceledException e) {
+ if (DBG) log(pendingIntent + " was not sent, it had been canceled.");
+ mPendingIntentWakeLock.release();
+ releasePendingNetworkRequest(pendingIntent);
+ }
+ // ...otherwise, mPendingIntentWakeLock.release() gets called by onSendFinished()
+ }
+
+ @Override
+ public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
+ String resultData, Bundle resultExtras) {
+ if (DBG) log("Finished sending " + pendingIntent);
+ mPendingIntentWakeLock.release();
+ releasePendingNetworkRequest(pendingIntent);
+ }
+
private void callCallbackForRequest(NetworkRequestInfo nri,
NetworkAgentInfo networkAgent, int notificationType) {
if (nri.messenger == null) return; // Default request has no msgr
@@ -4156,7 +4287,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// } else if (nai.networkMonitor.isEvaluating()) {
// notifyType = NetworkCallbacks.callCallbackForRequest(request, nai, notifyType);
// }
- callCallbackForRequest(nri, nai, notifyType);
+ if (nri.mPendingIntent == null) {
+ callCallbackForRequest(nri, nai, notifyType);
+ } else {
+ sendPendingIntentForRequest(nri, nai, notifyType);
+ }
}
private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, boolean connected, int type) {
@@ -4215,7 +4350,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
NetworkRequestInfo nri = mNetworkRequests.get(nr);
if (VDBG) log(" sending notification for " + nr);
- callCallbackForRequest(nri, networkAgent, notifyType);
+ if (nri.mPendingIntent == null) {
+ callCallbackForRequest(nri, networkAgent, notifyType);
+ } else {
+ sendPendingIntentForRequest(nri, networkAgent, notifyType);
+ }
}
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index b708c3f..11ba8e8 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -18,49 +18,38 @@ package com.android.server;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
import static android.content.Context.USER_SERVICE;
import static android.Manifest.permission.READ_PROFILE;
-import android.database.Cursor;
+
import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteStatement;
import android.os.Binder;
-import android.os.Environment;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.storage.IMountService;
import android.os.ServiceManager;
-import android.os.storage.StorageManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.provider.Settings.SettingNotFoundException;
-import android.security.KeyChain;
-import android.security.KeyChain.KeyChainConnection;
import android.security.KeyStore;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.ILockSettingsObserver;
import com.android.internal.widget.LockPatternUtils;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -73,27 +62,17 @@ import java.util.List;
*/
public class LockSettingsService extends ILockSettings.Stub {
- private static final String PERMISSION = "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE";
+ private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
- private final DatabaseHelper mOpenHelper;
- private static final String TAG = "LockSettingsService";
- private static final String TABLE = "locksettings";
- private static final String COLUMN_KEY = "name";
- private static final String COLUMN_USERID = "user";
- private static final String COLUMN_VALUE = "value";
+ private static final String TAG = "LockSettingsService";
- private static final String[] COLUMNS_FOR_QUERY = {
- COLUMN_VALUE
- };
+ private final Context mContext;
- private static final String SYSTEM_DIRECTORY = "/system/";
- private static final String LOCK_PATTERN_FILE = "gesture.key";
- private static final String LOCK_PASSWORD_FILE = "password.key";
+ private final LockSettingsStorage mStorage;
- private final Context mContext;
private LockPatternUtils mLockPatternUtils;
private boolean mFirstCallToVold;
@@ -102,7 +81,6 @@ public class LockSettingsService extends ILockSettings.Stub {
public LockSettingsService(Context context) {
mContext = context;
// Open the database
- mOpenHelper = new DatabaseHelper(mContext);
mLockPatternUtils = new LockPatternUtils(context);
mFirstCallToVold = true;
@@ -110,6 +88,18 @@ public class LockSettingsService extends ILockSettings.Stub {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_ADDED);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+
+ mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
+ @Override
+ public void initialize(SQLiteDatabase db) {
+ // Get the lockscreen default from a system property, if available
+ boolean lockScreenDisable = SystemProperties.getBoolean(
+ "ro.lockscreen.disable.default", false);
+ if (lockScreenDisable) {
+ mStorage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
+ }
+ }
+ });
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -220,29 +210,31 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public void setBoolean(String key, boolean value, int userId) throws RemoteException {
checkWritePermission(userId);
-
- writeToDb(key, value ? "1" : "0", userId);
+ setStringUnchecked(key, userId, value ? "1" : "0");
}
@Override
public void setLong(String key, long value, int userId) throws RemoteException {
checkWritePermission(userId);
-
- writeToDb(key, Long.toString(value), userId);
+ setStringUnchecked(key, userId, Long.toString(value));
}
@Override
public void setString(String key, String value, int userId) throws RemoteException {
checkWritePermission(userId);
+ setStringUnchecked(key, userId, value);
+ }
- writeToDb(key, value, userId);
+ private void setStringUnchecked(String key, int userId, String value) {
+ mStorage.writeKeyValue(key, value, userId);
+ notifyObservers(key, userId);
}
@Override
public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
checkReadPermission(key, userId);
- String value = readFromDb(key, null, userId);
+ String value = mStorage.readKeyValue(key, null, userId);
return TextUtils.isEmpty(value) ?
defaultValue : (value.equals("1") || value.equals("true"));
}
@@ -251,7 +243,7 @@ public class LockSettingsService extends ILockSettings.Stub {
public long getLong(String key, long defaultValue, int userId) throws RemoteException {
checkReadPermission(key, userId);
- String value = readFromDb(key, null, userId);
+ String value = mStorage.readKeyValue(key, null, userId);
return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
}
@@ -259,7 +251,7 @@ public class LockSettingsService extends ILockSettings.Stub {
public String getString(String key, String defaultValue, int userId) throws RemoteException {
checkReadPermission(key, userId);
- return readFromDb(key, defaultValue, userId);
+ return mStorage.readKeyValue(key, defaultValue, userId);
}
@Override
@@ -308,57 +300,18 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
- private int getUserParentOrSelfId(int userId) {
- if (userId != 0) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
- final UserInfo pi = um.getProfileParent(userId);
- if (pi != null) {
- return pi.id;
- }
- }
- return userId;
- }
-
- private String getLockPatternFilename(int userId) {
- String dataSystemDirectory =
- android.os.Environment.getDataDirectory().getAbsolutePath() +
- SYSTEM_DIRECTORY;
- userId = getUserParentOrSelfId(userId);
- if (userId == 0) {
- // Leave it in the same place for user 0
- return dataSystemDirectory + LOCK_PATTERN_FILE;
- } else {
- return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE)
- .getAbsolutePath();
- }
- }
-
- private String getLockPasswordFilename(int userId) {
- userId = getUserParentOrSelfId(userId);
- String dataSystemDirectory =
- android.os.Environment.getDataDirectory().getAbsolutePath() +
- SYSTEM_DIRECTORY;
- if (userId == 0) {
- // Leave it in the same place for user 0
- return dataSystemDirectory + LOCK_PASSWORD_FILE;
- } else {
- return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE)
- .getAbsolutePath();
- }
- }
-
@Override
public boolean havePassword(int userId) throws RemoteException {
// Do we need a permissions check here?
- return new File(getLockPasswordFilename(userId)).length() > 0;
+ return mStorage.hasPassword(userId);
}
@Override
public boolean havePattern(int userId) throws RemoteException {
// Do we need a permissions check here?
- return new File(getLockPatternFilename(userId)).length() > 0;
+ return mStorage.hasPattern(userId);
}
private void maybeUpdateKeystore(String password, int userHandle) {
@@ -394,7 +347,7 @@ public class LockSettingsService extends ILockSettings.Stub {
final byte[] hash = LockPatternUtils.patternToHash(
LockPatternUtils.stringToPattern(pattern));
- writeFile(getLockPatternFilename(userId), hash);
+ mStorage.writePatternHash(hash, userId);
}
@Override
@@ -403,68 +356,46 @@ public class LockSettingsService extends ILockSettings.Stub {
maybeUpdateKeystore(password, userId);
- writeFile(getLockPasswordFilename(userId),
- mLockPatternUtils.passwordToHash(password, userId));
+ mStorage.writePasswordHash(mLockPatternUtils.passwordToHash(password, userId), userId);
}
@Override
public boolean checkPattern(String pattern, int userId) throws RemoteException {
checkPasswordReadPermission(userId);
- try {
- // Read all the bytes from the file
- RandomAccessFile raf = new RandomAccessFile(getLockPatternFilename(userId), "r");
- final byte[] stored = new byte[(int) raf.length()];
- int got = raf.read(stored, 0, stored.length);
- raf.close();
- if (got <= 0) {
- return true;
- }
- // Compare the hash from the file with the entered pattern's hash
- final byte[] hash = LockPatternUtils.patternToHash(
- LockPatternUtils.stringToPattern(pattern));
- final boolean matched = Arrays.equals(stored, hash);
- if (matched && !TextUtils.isEmpty(pattern)) {
- maybeUpdateKeystore(pattern, userId);
- }
- return matched;
- } catch (FileNotFoundException fnfe) {
- Slog.e(TAG, "Cannot read file " + fnfe);
- } catch (IOException ioe) {
- Slog.e(TAG, "Cannot read file " + ioe);
+ byte[] hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(pattern));
+ byte[] storedHash = mStorage.readPatternHash(userId);
+
+ if (storedHash == null) {
+ return true;
}
- return true;
+
+ boolean matched = Arrays.equals(hash, storedHash);
+ if (matched && !TextUtils.isEmpty(pattern)) {
+ maybeUpdateKeystore(pattern, userId);
+ }
+ return matched;
}
@Override
public boolean checkPassword(String password, int userId) throws RemoteException {
checkPasswordReadPermission(userId);
- try {
- // Read all the bytes from the file
- RandomAccessFile raf = new RandomAccessFile(getLockPasswordFilename(userId), "r");
- final byte[] stored = new byte[(int) raf.length()];
- int got = raf.read(stored, 0, stored.length);
- raf.close();
- if (got <= 0) {
- return true;
- }
- // Compare the hash from the file with the entered password's hash
- final byte[] hash = mLockPatternUtils.passwordToHash(password, userId);
- final boolean matched = Arrays.equals(stored, hash);
- if (matched && !TextUtils.isEmpty(password)) {
- maybeUpdateKeystore(password, userId);
- }
- return matched;
- } catch (FileNotFoundException fnfe) {
- Slog.e(TAG, "Cannot read file " + fnfe);
- } catch (IOException ioe) {
- Slog.e(TAG, "Cannot read file " + ioe);
+ byte[] hash = mLockPatternUtils.passwordToHash(password, userId);
+ byte[] storedHash = mStorage.readPasswordHash(userId);
+
+ if (storedHash == null) {
+ return true;
+ }
+
+ boolean matched = Arrays.equals(hash, storedHash);
+ if (matched && !TextUtils.isEmpty(password)) {
+ maybeUpdateKeystore(password, userId);
}
- return true;
+ return matched;
}
@Override
- public boolean checkVoldPassword(int userId) throws RemoteException {
+ public boolean checkVoldPassword(int userId) throws RemoteException {
if (!mFirstCallToVold) {
return false;
}
@@ -512,166 +443,14 @@ public class LockSettingsService extends ILockSettings.Stub {
public void removeUser(int userId) {
checkWritePermission(userId);
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- try {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
- final UserInfo parentInfo = um.getProfileParent(userId);
- if (parentInfo == null) {
- // This user owns its lock settings files - safe to delete them
- File file = new File(getLockPasswordFilename(userId));
- if (file.exists()) {
- file.delete();
- }
- file = new File(getLockPatternFilename(userId));
- if (file.exists()) {
- file.delete();
- }
- }
-
- db.beginTransaction();
- db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null);
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
+ mStorage.removeUser(userId);
+ notifyObservers(null /* key */, userId);
final KeyStore ks = KeyStore.getInstance();
final int userUid = UserHandle.getUid(userId, Process.SYSTEM_UID);
ks.resetUid(userUid);
}
- private void writeFile(String name, byte[] hash) {
- try {
- // Write the hash to file
- RandomAccessFile raf = new RandomAccessFile(name, "rw");
- // Truncate the file if pattern is null, to clear the lock
- if (hash == null || hash.length == 0) {
- raf.setLength(0);
- } else {
- raf.write(hash, 0, hash.length);
- }
- raf.close();
- } catch (IOException ioe) {
- Slog.e(TAG, "Error writing to file " + ioe);
- }
- }
-
- private void writeToDb(String key, String value, int userId) {
- writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId);
- notifyObservers(key, userId);
- }
-
- private void writeToDb(SQLiteDatabase db, String key, String value, int userId) {
- ContentValues cv = new ContentValues();
- cv.put(COLUMN_KEY, key);
- cv.put(COLUMN_USERID, userId);
- cv.put(COLUMN_VALUE, value);
-
- db.beginTransaction();
- try {
- db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
- new String[] {key, Integer.toString(userId)});
- db.insert(TABLE, null, cv);
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
- }
-
- private String readFromDb(String key, String defaultValue, int userId) {
- Cursor cursor;
- String result = defaultValue;
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY,
- COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?",
- new String[] { Integer.toString(userId), key },
- null, null, null)) != null) {
- if (cursor.moveToFirst()) {
- result = cursor.getString(0);
- }
- cursor.close();
- }
- return result;
- }
-
- class DatabaseHelper extends SQLiteOpenHelper {
- private static final String TAG = "LockSettingsDB";
- private static final String DATABASE_NAME = "locksettings.db";
-
- private static final int DATABASE_VERSION = 2;
-
- public DatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
- setWriteAheadLoggingEnabled(true);
- }
-
- private void createTable(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE " + TABLE + " (" +
- "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
- COLUMN_KEY + " TEXT," +
- COLUMN_USERID + " INTEGER," +
- COLUMN_VALUE + " TEXT" +
- ");");
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- createTable(db);
- initializeDefaults(db);
- }
-
- private void initializeDefaults(SQLiteDatabase db) {
- // Get the lockscreen default from a system property, if available
- boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default",
- false);
- if (lockScreenDisable) {
- writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
- }
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
- int upgradeVersion = oldVersion;
- if (upgradeVersion == 1) {
- // Set the initial value for {@link LockPatternUtils#LOCKSCREEN_WIDGETS_ENABLED}
- // during upgrade based on whether each user previously had widgets in keyguard.
- maybeEnableWidgetSettingForUsers(db);
- upgradeVersion = 2;
- }
-
- if (upgradeVersion != DATABASE_VERSION) {
- Log.w(TAG, "Failed to upgrade database!");
- }
- }
-
- private void maybeEnableWidgetSettingForUsers(SQLiteDatabase db) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
- final ContentResolver cr = mContext.getContentResolver();
- final List<UserInfo> users = um.getUsers();
- for (int i = 0; i < users.size(); i++) {
- final int userId = users.get(i).id;
- final boolean enabled = mLockPatternUtils.hasWidgetsEnabledInKeyguard(userId);
- Log.v(TAG, "Widget upgrade uid=" + userId + ", enabled="
- + enabled + ", w[]=" + mLockPatternUtils.getAppWidgets());
- loadSetting(db, LockPatternUtils.LOCKSCREEN_WIDGETS_ENABLED, userId, enabled);
- }
- }
-
- private void loadSetting(SQLiteDatabase db, String key, int userId, boolean value) {
- SQLiteStatement stmt = null;
- try {
- stmt = db.compileStatement(
- "INSERT OR REPLACE INTO locksettings(name,user,value) VALUES(?,?,?);");
- stmt.bindString(1, key);
- stmt.bindLong(2, userId);
- stmt.bindLong(3, value ? 1 : 0);
- stmt.execute();
- } finally {
- if (stmt != null) stmt.close();
- }
- }
- }
-
private static final String[] VALID_SETTINGS = new String[] {
LockPatternUtils.LOCKOUT_PERMANENT_KEY,
LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
new file mode 100644
index 0000000..acbf8ef
--- /dev/null
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -0,0 +1,307 @@
+/*
+ * 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.server;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.os.Environment;
+import android.os.UserManager;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import static android.content.Context.USER_SERVICE;
+
+/**
+ * Storage for the lock settings service.
+ */
+class LockSettingsStorage {
+
+ private static final String TAG = "LockSettingsStorage";
+ private static final String TABLE = "locksettings";
+
+ private static final String COLUMN_KEY = "name";
+ private static final String COLUMN_USERID = "user";
+ private static final String COLUMN_VALUE = "value";
+
+ private static final String[] COLUMNS_FOR_QUERY = {
+ COLUMN_VALUE
+ };
+
+ private static final String SYSTEM_DIRECTORY = "/system/";
+ private static final String LOCK_PATTERN_FILE = "gesture.key";
+ private static final String LOCK_PASSWORD_FILE = "password.key";
+
+ private final DatabaseHelper mOpenHelper;
+ private final Context mContext;
+ private final Object mFileWriteLock = new Object();
+
+ LockSettingsStorage(Context context, Callback callback) {
+ mContext = context;
+ mOpenHelper = new DatabaseHelper(context, callback);
+ }
+
+ void writeKeyValue(String key, String value, int userId) {
+ writeKeyValue(mOpenHelper.getWritableDatabase(), key, value, userId);
+ }
+
+ void writeKeyValue(SQLiteDatabase db, String key, String value, int userId) {
+ ContentValues cv = new ContentValues();
+ cv.put(COLUMN_KEY, key);
+ cv.put(COLUMN_USERID, userId);
+ cv.put(COLUMN_VALUE, value);
+
+ db.beginTransaction();
+ try {
+ db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
+ new String[] {key, Integer.toString(userId)});
+ db.insert(TABLE, null, cv);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+
+ }
+
+ String readKeyValue(String key, String defaultValue, int userId) {
+ Cursor cursor;
+ String result = defaultValue;
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY,
+ COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?",
+ new String[] { Integer.toString(userId), key },
+ null, null, null)) != null) {
+ if (cursor.moveToFirst()) {
+ result = cursor.getString(0);
+ }
+ cursor.close();
+ }
+ return result;
+ }
+
+ byte[] readPasswordHash(int userId) {
+ final byte[] stored = readFile(getLockPasswordFilename(userId), userId);
+ if (stored != null && stored.length > 0) {
+ return stored;
+ }
+ return null;
+ }
+
+ byte[] readPatternHash(int userId) {
+ final byte[] stored = readFile(getLockPatternFilename(userId), userId);
+ if (stored != null && stored.length > 0) {
+ return stored;
+ }
+ return null;
+ }
+
+ boolean hasPassword(int userId) {
+ return hasFile(getLockPasswordFilename(userId), userId);
+ }
+
+ boolean hasPattern(int userId) {
+ return hasFile(getLockPatternFilename(userId), userId);
+ }
+
+ private boolean hasFile(String name, int userId) {
+ byte[] contents = readFile(name, userId);
+ return contents != null && contents.length > 0;
+ }
+
+ private byte[] readFile(String name, int userId) {
+ RandomAccessFile raf = null;
+ byte[] stored = null;
+ try {
+ raf = new RandomAccessFile(name, "r");
+ stored = new byte[(int) raf.length()];
+ raf.readFully(stored, 0, stored.length);
+ raf.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot read file " + e);
+ } finally {
+ if (raf != null) {
+ try {
+ raf.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Error closing file " + e);
+ }
+ }
+ }
+ return stored;
+ }
+
+ private void writeFile(String name, byte[] hash, int userId) {
+ synchronized (mFileWriteLock) {
+ RandomAccessFile raf = null;
+ try {
+ // Write the hash to file
+ raf = new RandomAccessFile(name, "rw");
+ // Truncate the file if pattern is null, to clear the lock
+ if (hash == null || hash.length == 0) {
+ raf.setLength(0);
+ } else {
+ raf.write(hash, 0, hash.length);
+ }
+ raf.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Error writing to file " + e);
+ } finally {
+ if (raf != null) {
+ try {
+ raf.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Error closing file " + e);
+ }
+ }
+ }
+ }
+ }
+
+ public void writePatternHash(byte[] hash, int userId) {
+ writeFile(getLockPatternFilename(userId), hash, userId);
+ }
+
+ public void writePasswordHash(byte[] hash, int userId) {
+ writeFile(getLockPasswordFilename(userId), hash, userId);
+ }
+
+
+ private String getLockPatternFilename(int userId) {
+ String dataSystemDirectory =
+ android.os.Environment.getDataDirectory().getAbsolutePath() +
+ SYSTEM_DIRECTORY;
+ userId = getUserParentOrSelfId(userId);
+ if (userId == 0) {
+ // Leave it in the same place for user 0
+ return dataSystemDirectory + LOCK_PATTERN_FILE;
+ } else {
+ return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE)
+ .getAbsolutePath();
+ }
+ }
+
+ private String getLockPasswordFilename(int userId) {
+ userId = getUserParentOrSelfId(userId);
+ String dataSystemDirectory =
+ android.os.Environment.getDataDirectory().getAbsolutePath() +
+ SYSTEM_DIRECTORY;
+ if (userId == 0) {
+ // Leave it in the same place for user 0
+ return dataSystemDirectory + LOCK_PASSWORD_FILE;
+ } else {
+ return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE)
+ .getAbsolutePath();
+ }
+ }
+
+ private int getUserParentOrSelfId(int userId) {
+ if (userId != 0) {
+ final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
+ final UserInfo pi = um.getProfileParent(userId);
+ if (pi != null) {
+ return pi.id;
+ }
+ }
+ return userId;
+ }
+
+
+ public void removeUser(int userId) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+
+ final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
+ final UserInfo parentInfo = um.getProfileParent(userId);
+
+ synchronized (mFileWriteLock) {
+ if (parentInfo == null) {
+ // This user owns its lock settings files - safe to delete them
+ File file = new File(getLockPasswordFilename(userId));
+ if (file.exists()) {
+ file.delete();
+ }
+ file = new File(getLockPatternFilename(userId));
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+ }
+
+ try {
+ db.beginTransaction();
+ db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+
+ interface Callback {
+ void initialize(SQLiteDatabase db);
+ }
+
+ class DatabaseHelper extends SQLiteOpenHelper {
+ private static final String TAG = "LockSettingsDB";
+ private static final String DATABASE_NAME = "locksettings.db";
+
+ private static final int DATABASE_VERSION = 2;
+
+ private final Callback mCallback;
+
+ public DatabaseHelper(Context context, Callback callback) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ setWriteAheadLoggingEnabled(true);
+ mCallback = callback;
+ }
+
+ private void createTable(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE " + TABLE + " (" +
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
+ COLUMN_KEY + " TEXT," +
+ COLUMN_USERID + " INTEGER," +
+ COLUMN_VALUE + " TEXT" +
+ ");");
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ createTable(db);
+ mCallback.initialize(db);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
+ int upgradeVersion = oldVersion;
+ if (upgradeVersion == 1) {
+ // Previously migrated lock screen widget settings. Now defunct.
+ upgradeVersion = 2;
+ }
+
+ if (upgradeVersion != DATABASE_VERSION) {
+ Log.w(TAG, "Failed to upgrade database!");
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index 96f9ab0..8c3b020 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -176,7 +176,6 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
if (buffer[i] == 0) {
final String rawEvent = new String(
buffer, start, i - start, StandardCharsets.UTF_8);
- log("RCV <- {" + rawEvent + "}");
boolean releaseWl = false;
try {
@@ -197,7 +196,6 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
mResponseQueue.add(event.getCmdNumber(), event);
}
} catch (IllegalArgumentException e) {
- log("Problem parsing message: " + rawEvent + " - " + e);
} finally {
if (releaseWl) {
mWakeLock.acquire();
@@ -209,7 +207,6 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
}
if (start == 0) {
final String rawEvent = new String(buffer, start, count, StandardCharsets.UTF_8);
- log("RCV incomplete <- {" + rawEvent + "}");
}
// We should end at the amount we read. If not, compact then
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 395e365..738917f 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -115,10 +115,10 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
@Override
public boolean clearScores() {
- // Only the active scorer or the system (who can broadcast BROADCAST_SCORE_NETWORKS) should
- // be allowed to flush all scores.
+ // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
+ // should be allowed to flush all scores.
if (NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid()) ||
- mContext.checkCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS) ==
+ mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
PackageManager.PERMISSION_GRANTED) {
clearInternal();
return true;
@@ -130,16 +130,25 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
@Override
public boolean setActiveScorer(String packageName) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS, TAG);
+ // TODO: For now, since SCORE_NETWORKS requires an app to be privileged, we allow such apps
+ // to directly set the scorer app rather than having to use the consent dialog. The
+ // assumption is that anyone bundling a scorer app with the system is trusted by the OEM to
+ // do the right thing and not enable this feature without explaining it to the user.
+ // In the future, should this API be opened to 3p apps, we will need to lock this down and
+ // figure out another way to streamline the UX.
+
+ // mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG);
+
return setScorerInternal(packageName);
}
@Override
public void disableScoring() {
- // Only the active scorer or the system (who can broadcast BROADCAST_SCORE_NETOWRKS) should
- // be allowed to disable scoring.
+ // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
+ // should be allowed to disable scoring.
if (NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid()) ||
- mContext.checkCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS) ==
+ mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
PackageManager.PERMISSION_GRANTED) {
// The return value is discarded here because at this point, the call should always
// succeed. The only reason for failure is if the new package is not a valid scorer, but
@@ -188,7 +197,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
@Override
public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
synchronized (mScoreCaches) {
if (mScoreCaches.containsKey(networkType)) {
throw new IllegalArgumentException(
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 6f378fd..de90aa2 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -72,7 +72,7 @@ public class PersistentDataBlockService extends SystemService {
private final String mDataBlockFile;
private final Object mLock = new Object();
- private int mAllowedAppId = -1;
+ private int mAllowedUid = -1;
/*
* Separate lock for OEM unlock related operations as they can happen in parallel with regular
* block operations.
@@ -86,11 +86,11 @@ public class PersistentDataBlockService extends SystemService {
mContext = context;
mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
mBlockDeviceSize = -1; // Load lazily
- mAllowedAppId = getAllowedAppId(UserHandle.USER_OWNER);
+ mAllowedUid = getAllowedUid(UserHandle.USER_OWNER);
}
- private int getAllowedAppId(int userHandle) {
+ private int getAllowedUid(int userHandle) {
String allowedPackage = mContext.getResources()
.getString(R.string.config_persistentDataPackageName);
PackageManager pm = mContext.getPackageManager();
@@ -101,7 +101,7 @@ public class PersistentDataBlockService extends SystemService {
// not expected
Slog.e(TAG, "not able to find package " + allowedPackage, e);
}
- return UserHandle.getAppId(allowedUid);
+ return allowedUid;
}
@Override
@@ -116,11 +116,17 @@ public class PersistentDataBlockService extends SystemService {
}
private void enforceUid(int callingUid) {
- if (UserHandle.getAppId(callingUid) != mAllowedAppId) {
+ if (callingUid != mAllowedUid) {
throw new SecurityException("uid " + callingUid + " not allowed to access PST");
}
}
+ private void enforceIsOwner() {
+ if (!Binder.getCallingUserHandle().isOwner()) {
+ throw new SecurityException("Only the Owner is allowed to change OEM unlock state");
+ }
+ }
+
private int getTotalDataSizeLocked(DataInputStream inputStream) throws IOException {
int totalDataSize;
int blockId = inputStream.readInt();
@@ -249,6 +255,7 @@ public class PersistentDataBlockService extends SystemService {
return;
}
enforceOemUnlockPermission();
+ enforceIsOwner();
FileOutputStream outputStream;
try {
outputStream = new FileOutputStream(new File(mDataBlockFile));
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index fcc5339..ba93213 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -596,7 +596,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
+ " phoneId=" + phoneId + " state=" + state);
}
if (((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) &&
- subIdMatch(r.subId, subId)) {
+ idMatch(r.subId, subId, phoneId)) {
try {
if (DBG) {
log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
@@ -641,7 +641,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
+ " phoneId=" + phoneId + " ss=" + signalStrength);
}
if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) &&
- subIdMatch(r.subId, subId)) {
+ idMatch(r.subId, subId, phoneId)) {
try {
if (DBG) {
log("notifySignalStrengthForSubscriber: callback.onSsS r=" + r
@@ -654,7 +654,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) &&
- subIdMatch(r.subId, subId)){
+ idMatch(r.subId, subId, phoneId)){
try {
int gsmSignalStrength = signalStrength.getGsmSignalStrength();
int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
@@ -696,7 +696,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mCellInfo.set(phoneId, cellInfo);
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
- subIdMatch(r.subId, subId)) {
+ idMatch(r.subId, subId, phoneId)) {
try {
if (DBG_LOC) {
log("notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r);
@@ -751,7 +751,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mMessageWaiting[phoneId] = mwi;
for (Record r : mRecords) {
if (((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) &&
- subIdMatch(r.subId, subId)) {
+ idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onMessageWaitingIndicatorChanged(mwi);
} catch (RemoteException ex) {
@@ -782,7 +782,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mCallForwarding[phoneId] = cfi;
for (Record r : mRecords) {
if (((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) &&
- subIdMatch(r.subId, subId)) {
+ idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onCallForwardingIndicatorChanged(cfi);
} catch (RemoteException ex) {
@@ -879,7 +879,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
for (Record r : mRecords) {
if (((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) &&
- subIdMatch(r.subId, subId)) {
+ idMatch(r.subId, subId, phoneId)) {
try {
log("Notify data connection state changed on sub: " +
subId);
@@ -965,7 +965,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mCellLocation[phoneId] = cellLocation;
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
- subIdMatch(r.subId, subId)) {
+ idMatch(r.subId, subId, phoneId)) {
try {
if (DBG_LOC) {
log("notifyCellLocation: cellLocation=" + cellLocation
@@ -1386,7 +1386,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
@Override
public String toString() {
- return mS + " " + mTime.toString() + " " + mSubId + " " + mPhoneId + " " + mState;
+ return mS + " Time " + mTime.toString() + " mSubId " + mSubId + " mPhoneId " + mPhoneId + " mState " + mState;
}
}
@@ -1429,8 +1429,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- boolean subIdMatch(int rSubId, int subId) {
+ boolean idMatch(int rSubId, int subId, int phoneId) {
if(rSubId == SubscriptionManager.DEFAULT_SUB_ID) {
+ if(subId < 0) {
+ // Invalid case, we need compare phoneId with default one.
+ return (mDefaultPhoneId == phoneId);
+ }
return (subId == mDefaultSubId);
} else {
return (rSubId == subId);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9179cc4..97847b5 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -952,10 +952,13 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
private boolean mWentToSleep = false;
+ static final int LOCK_SCREEN_HIDDEN = 0;
+ static final int LOCK_SCREEN_LEAVING = 1;
+ static final int LOCK_SCREEN_SHOWN = 2;
/**
* State of external call telling us if the lock screen is shown.
*/
- private boolean mLockScreenShown = false;
+ int mLockScreenShown = LOCK_SCREEN_HIDDEN;
/**
* Set if we are shutting down the system, similar to sleeping.
@@ -1836,8 +1839,8 @@ public final class ActivityManagerService extends ActivityManagerNative
ComponentName cn = tr.intent.getComponent();
if (cn != null && cn.getPackageName().equals(packageName)) {
- // If the package name matches, remove the task and kill the process
- removeTaskByIdLocked(tr.taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ // If the package name matches, remove the task
+ removeTaskByIdLocked(tr.taskId, true);
}
}
}
@@ -1891,9 +1894,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Prune all the tasks with removed components from the list of recent tasks
synchronized (ActivityManagerService.this) {
for (int i = tasksToRemove.size() - 1; i >= 0; i--) {
- // Remove the task but don't kill the process (since other components in that
- // package may still be running and in the background)
- removeTaskByIdLocked(tasksToRemove.get(i), 0);
+ removeTaskByIdLocked(tasksToRemove.get(i), false);
}
}
}
@@ -4313,9 +4314,9 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean res;
if (finishTask && r == rootR) {
// If requested, remove the task that is associated to this activity only if it
- // was the root activity in the task. The result code and data is ignored because
- // we don't support returning them across task boundaries.
- res = removeTaskByIdLocked(tr.taskId, 0);
+ // was the root activity in the task. The result code and data is ignored
+ // because we don't support returning them across task boundaries.
+ res = removeTaskByIdLocked(tr.taskId, false);
} else {
res = tr.stack.requestFinishActivityLocked(token, resultCode,
resultData, "app-request", true);
@@ -5142,7 +5143,7 @@ public final class ActivityManagerService extends ActivityManagerNative
tr.getBaseIntent().getComponent().getPackageName();
if (tr.userId != userId) continue;
if (!taskPackageName.equals(packageName)) continue;
- removeTaskByIdLocked(tr.taskId, 0);
+ removeTaskByIdLocked(tr.taskId, false);
}
}
@@ -6120,9 +6121,8 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
if (DEBUG_LOCKSCREEN) logLockScreen("");
mWindowManager.keyguardWaitingForActivityDrawn();
- if (mLockScreenShown) {
- mLockScreenShown = false;
- comeOutOfSleepIfNeededLocked();
+ if (mLockScreenShown == LOCK_SCREEN_SHOWN) {
+ mLockScreenShown = LOCK_SCREEN_LEAVING;
}
}
} finally {
@@ -8287,52 +8287,65 @@ public final class ActivityManagerService extends ActivityManagerNative
return mTaskPersister.getTaskDescriptionIcon(filename);
}
- private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {
+ private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) {
mRecentTasks.remove(tr);
tr.removedFromRecents(mTaskPersister);
- final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0;
- Intent baseIntent = new Intent(
- tr.intent != null ? tr.intent : tr.affinityIntent);
- ComponentName component = baseIntent.getComponent();
+ ComponentName component = tr.getBaseIntent().getComponent();
if (component == null) {
- Slog.w(TAG, "Now component for base intent of task: " + tr);
+ Slog.w(TAG, "No component for base intent of task: " + tr);
return;
}
- // Find any running services associated with this app.
- mServices.cleanUpRemovedTaskLocked(tr, component, baseIntent);
+ if (!killProcess) {
+ return;
+ }
- if (killProcesses) {
- // Find any running processes associated with this app.
- final String pkg = component.getPackageName();
- ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
- ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
- for (int i=0; i<pmap.size(); i++) {
- SparseArray<ProcessRecord> uids = pmap.valueAt(i);
- for (int j=0; j<uids.size(); j++) {
- ProcessRecord proc = uids.valueAt(j);
- if (proc.userId != tr.userId) {
- continue;
- }
- if (!proc.pkgList.containsKey(pkg)) {
- continue;
- }
- procs.add(proc);
- }
- }
+ // Determine if the process(es) for this task should be killed.
+ final String pkg = component.getPackageName();
+ ArrayList<ProcessRecord> procsToKill = new ArrayList<ProcessRecord>();
+ ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
+ for (int i = 0; i < pmap.size(); i++) {
- // Kill the running processes.
- for (int i=0; i<procs.size(); i++) {
- ProcessRecord pr = procs.get(i);
- if (pr == mHomeProcess) {
+ SparseArray<ProcessRecord> uids = pmap.valueAt(i);
+ for (int j = 0; j < uids.size(); j++) {
+ ProcessRecord proc = uids.valueAt(j);
+ if (proc.userId != tr.userId) {
+ // Don't kill process for a different user.
+ continue;
+ }
+ if (proc == mHomeProcess) {
// Don't kill the home process along with tasks from the same package.
continue;
}
- if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
- pr.kill("remove task", true);
- } else {
- pr.waitingToKill = "remove task";
+ if (!proc.pkgList.containsKey(pkg)) {
+ // Don't kill process that is not associated with this task.
+ continue;
}
+
+ for (int k = 0; k < proc.activities.size(); k++) {
+ TaskRecord otherTask = proc.activities.get(k).task;
+ if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
+ // Don't kill process(es) that has an activity in a different task that is
+ // also in recents.
+ return;
+ }
+ }
+
+ // Add process to kill list.
+ procsToKill.add(proc);
+ }
+ }
+
+ // Find any running services associated with this app and stop if needed.
+ mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
+
+ // Kill the running processes.
+ for (int i = 0; i < procsToKill.size(); i++) {
+ ProcessRecord pr = procsToKill.get(i);
+ if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+ pr.kill("remove task", true);
+ } else {
+ pr.waitingToKill = "remove task";
}
}
}
@@ -8341,15 +8354,14 @@ public final class ActivityManagerService extends ActivityManagerNative
* Removes the task with the specified task id.
*
* @param taskId Identifier of the task to be removed.
- * @param flags Additional operational flags. May be 0 or
- * {@link ActivityManager#REMOVE_TASK_KILL_PROCESS}.
+ * @param killProcess Kill any process associated with the task if possible.
* @return Returns true if the given task was found and removed.
*/
- private boolean removeTaskByIdLocked(int taskId, int flags) {
+ private boolean removeTaskByIdLocked(int taskId, boolean killProcess) {
TaskRecord tr = recentTaskForIdLocked(taskId);
if (tr != null) {
tr.removeTaskActivitiesLocked();
- cleanUpRemovedTaskLocked(tr, flags);
+ cleanUpRemovedTaskLocked(tr, killProcess);
if (tr.isPersistable) {
notifyTaskPersisterLocked(null, true);
}
@@ -8359,19 +8371,19 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public boolean removeTask(int taskId, int flags) {
+ public boolean removeTask(int taskId) {
synchronized (this) {
enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
"removeTask()");
long ident = Binder.clearCallingIdentity();
try {
- return removeTaskByIdLocked(taskId, flags);
+ return removeTaskByIdLocked(taskId, true);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
-
+
/**
* TODO: Add mController hook
*/
@@ -9947,14 +9959,23 @@ public final class ActivityManagerService extends ActivityManagerNative
Binder.restoreCallingIdentity(origId);
}
+ private String lockScreenShownToString() {
+ switch (mLockScreenShown) {
+ case LOCK_SCREEN_HIDDEN: return "LOCK_SCREEN_HIDDEN";
+ case LOCK_SCREEN_LEAVING: return "LOCK_SCREEN_LEAVING";
+ case LOCK_SCREEN_SHOWN: return "LOCK_SCREEN_SHOWN";
+ default: return "Unknown=" + mLockScreenShown;
+ }
+ }
+
void logLockScreen(String msg) {
if (DEBUG_LOCKSCREEN) Slog.d(TAG, Debug.getCallers(2) + ":" + msg +
- " mLockScreenShown=" + mLockScreenShown + " mWentToSleep=" +
+ " mLockScreenShown=" + lockScreenShownToString() + " mWentToSleep=" +
mWentToSleep + " mSleeping=" + mSleeping);
}
- private void comeOutOfSleepIfNeededLocked() {
- if ((!mWentToSleep && !mLockScreenShown) || mRunningVoice) {
+ void comeOutOfSleepIfNeededLocked() {
+ if ((!mWentToSleep && mLockScreenShown == LOCK_SCREEN_HIDDEN) || mRunningVoice) {
if (mSleeping) {
mSleeping = false;
mStackSupervisor.comeOutOfSleepIfNeededLocked();
@@ -9991,7 +10012,7 @@ public final class ActivityManagerService extends ActivityManagerNative
long ident = Binder.clearCallingIdentity();
try {
if (DEBUG_LOCKSCREEN) logLockScreen(" shown=" + shown);
- mLockScreenShown = shown;
+ mLockScreenShown = shown ? LOCK_SCREEN_SHOWN : LOCK_SCREEN_HIDDEN;
comeOutOfSleepIfNeededLocked();
} finally {
Binder.restoreCallingIdentity(ident);
@@ -12757,9 +12778,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
if (dumpPackage == null) {
- if (mSleeping || mWentToSleep || mLockScreenShown) {
+ if (mSleeping || mWentToSleep || mLockScreenShown != LOCK_SCREEN_HIDDEN) {
pw.println(" mSleeping=" + mSleeping + " mWentToSleep=" + mWentToSleep
- + " mLockScreenShown " + mLockScreenShown);
+ + " mLockScreenShown " + lockScreenShownToString());
}
if (mShuttingDown || mRunningVoice) {
pw.print(" mShuttingDown=" + mShuttingDown + " mRunningVoice=" + mRunningVoice);
@@ -19167,16 +19188,9 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (ActivityManagerService.this) {
long origId = Binder.clearCallingIdentity();
try {
- TaskRecord tr = recentTaskForIdLocked(mTaskId);
- if (tr == null) {
+ if (!removeTaskByIdLocked(mTaskId, false)) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
}
- // Only kill the process if we are not a new document
- int flags = tr.getBaseIntent().getFlags();
- boolean isDocument = (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) ==
- Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
- removeTaskByIdLocked(mTaskId,
- !isDocument ? ActivityManager.REMOVE_TASK_KILL_PROCESS : 0);
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index e1b8278..b955011 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -241,9 +241,6 @@ final class ActivityStack {
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
- /** Used to keep resumeTopActivityLocked() from being entered recursively */
- private boolean inResumeTopActivity;
-
static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
@@ -835,7 +832,7 @@ final class ActivityStack {
prev.task.touchActiveTime();
clearLaunchTime(prev);
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
- if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task)) {
+ if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
prev.updateThumbnail(screenshotActivities(prev), null);
}
stopFullyDrawnTraceIfNeeded();
@@ -1468,7 +1465,7 @@ final class ActivityStack {
}
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
- if (inResumeTopActivity) {
+ if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
@@ -1476,10 +1473,14 @@ final class ActivityStack {
boolean result = false;
try {
// Protect against recursion.
- inResumeTopActivity = true;
+ mStackSupervisor.inResumeTopActivity = true;
+ if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
+ mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
+ mService.comeOutOfSleepIfNeededLocked();
+ }
result = resumeTopActivityInnerLocked(prev, options);
} finally {
- inResumeTopActivity = false;
+ mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index cc7026a..079df7d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -274,6 +274,9 @@ public final class ActivityStackSupervisor implements DisplayListener {
final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
= new ArrayList<PendingActivityLaunch>();
+ /** Used to keep resumeTopActivityLocked() from being entered recursively */
+ boolean inResumeTopActivity;
+
/**
* Description of a request to start a new activity, which has been held
* due to app switches being disabled.
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 5b22255..843a0cb 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -235,22 +235,16 @@ final class ProcessList {
Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs);
}
- // We've now baked in the increase to the basic oom values above, since
- // they seem to be useful more generally for devices that are tight on
- // memory than just for 64 bit. This should probably have some more
- // tuning done, so not deleting it quite yet...
- final boolean is64bit = false; //Build.SUPPORTED_64_BIT_ABIS.length > 0;
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+ // Increase the high min-free levels for cached processes for 64-bit
+ mOomMinFreeHigh[4] = 225000;
+ mOomMinFreeHigh[5] = 325000;
+ }
for (int i=0; i<mOomAdj.length; i++) {
int low = mOomMinFreeLow[i];
int high = mOomMinFreeHigh[i];
mOomMinFree[i] = (int)(low + ((high-low)*scale));
- if (is64bit) {
- // On 64 bit devices, we consume more baseline RAM, because 64 bit is cool!
- // To avoid being all pagey and stuff, scale up the memory levels to
- // give us some breathing room.
- mOomMinFree[i] = (3*mOomMinFree[i])/2;
- }
}
if (minfree_abs >= 0) {
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 238402f..debda14 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -191,8 +191,8 @@ public class PermissionMonitor {
}
try {
if (add) {
- mNetd.setPermission(CHANGE_NETWORK_STATE, toIntArray(network));
- mNetd.setPermission(CONNECTIVITY_INTERNAL, toIntArray(system));
+ mNetd.setPermission("NETWORK", toIntArray(network));
+ mNetd.setPermission("SYSTEM", toIntArray(system));
} else {
mNetd.clearPermission(toIntArray(network));
mNetd.clearPermission(toIntArray(system));
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 45d3771..d919bf6 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -21,7 +21,6 @@ import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
-import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -120,6 +119,7 @@ class AutomaticBrightnessController {
// The minimum and maximum screen brightnesses.
private final int mScreenBrightnessRangeMinimum;
private final int mScreenBrightnessRangeMaximum;
+ private final float mDozeScaleFactor;
// Amount of time to delay auto-brightness after screen on while waiting for
// the light sensor to warm-up in milliseconds.
@@ -171,9 +171,12 @@ class AutomaticBrightnessController {
// The last screen auto-brightness gamma. (For printing in dump() only.)
private float mLastScreenAutoBrightnessGamma = 1.0f;
+ // Are we going to adjust brightness while dozing.
+ private boolean mDozing;
+
public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
- SensorManager sensorManager, Spline autoBrightnessSpline,
- int lightSensorWarmUpTime, int brightnessMin, int brightnessMax) {
+ SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
+ int brightnessMin, int brightnessMax, float dozeScaleFactor) {
mCallbacks = callbacks;
mTwilight = LocalServices.getService(TwilightManager.class);
mSensorManager = sensorManager;
@@ -181,6 +184,7 @@ class AutomaticBrightnessController {
mScreenBrightnessRangeMinimum = brightnessMin;
mScreenBrightnessRangeMaximum = brightnessMax;
mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime;
+ mDozeScaleFactor = dozeScaleFactor;
mHandler = new AutomaticBrightnessHandler(looper);
mAmbientLightRingBuffer = new AmbientLightRingBuffer();
@@ -195,11 +199,20 @@ class AutomaticBrightnessController {
}
public int getAutomaticScreenBrightness() {
+ if (mDozing) {
+ return (int) (mScreenAutoBrightness * mDozeScaleFactor);
+ }
return mScreenAutoBrightness;
}
- public void configure(boolean enable, float adjustment) {
- boolean changed = setLightSensorEnabled(enable);
+ public void configure(boolean enable, float adjustment, boolean dozing) {
+ // While dozing, the application processor may be suspended which will prevent us from
+ // receiving new information from the light sensor. On some devices, we may be able to
+ // switch to a wake-up light sensor instead but for now we will simply disable the sensor
+ // and hold onto the last computed screen auto brightness. We save the dozing flag for
+ // debugging purposes.
+ mDozing = dozing;
+ boolean changed = setLightSensorEnabled(enable && !dozing);
changed |= setScreenAutoBrightnessAdjustment(adjustment);
if (changed) {
updateAutoBrightness(false /*sendUpdate*/);
@@ -230,6 +243,7 @@ class AutomaticBrightnessController {
pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
pw.println(" mScreenAutoBrightnessAdjustment=" + mScreenAutoBrightnessAdjustment);
pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
+ pw.println(" mDozing=" + mDozing);
}
private boolean setLightSensorEnabled(boolean enable) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1d8003b..81cd94b 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -155,6 +155,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// True if auto-brightness should be used.
private boolean mUseSoftwareAutoBrightnessConfig;
+ // True if should use light sensor to automatically determine doze screen brightness.
+ private final boolean mAllowAutoBrightnessWhileDozingConfig;
+
// True if we should fade the screen while turning it off, false if we should play
// a stylish color fade animation instead.
private boolean mColorFadeFadesConfig;
@@ -295,6 +298,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
com.android.internal.R.bool.config_automatic_brightness_available);
+
+ mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
+
if (mUseSoftwareAutoBrightnessConfig) {
int[] lux = resources.getIntArray(
com.android.internal.R.array.config_autoBrightnessLevels);
@@ -302,6 +309,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
int lightSensorWarmUpTimeConfig = resources.getInteger(
com.android.internal.R.integer.config_lightSensorWarmupTime);
+ final float dozeScaleFactor = resources.getFraction(
+ com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
+ 1, 1);
Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
if (screenAutoBrightnessSpline == null) {
@@ -326,7 +336,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAutomaticBrightnessController = new AutomaticBrightnessController(this,
handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
- mScreenBrightnessRangeMaximum);
+ mScreenBrightnessRangeMaximum, dozeScaleFactor);
}
}
@@ -523,7 +533,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} else {
state = Display.STATE_DOZE;
}
- brightness = mPowerRequest.dozeScreenBrightness;
+ if (!mAllowAutoBrightnessWhileDozingConfig) {
+ brightness = mPowerRequest.dozeScreenBrightness;
+ }
break;
case DisplayPowerRequest.POLICY_DIM:
case DisplayPowerRequest.POLICY_BRIGHT:
@@ -577,19 +589,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
brightness = PowerManager.BRIGHTNESS_ON;
}
- // Use default brightness when dozing unless overridden.
- if (brightness < 0 && (state == Display.STATE_DOZE
- || state == Display.STATE_DOZE_SUSPEND)) {
- brightness = mScreenBrightnessDozeConfig;
- }
-
// Configure auto-brightness.
boolean autoBrightnessEnabled = false;
if (mAutomaticBrightnessController != null) {
+ final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
+ && (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
autoBrightnessEnabled = mPowerRequest.useAutoBrightness
- && state == Display.STATE_ON && brightness < 0;
+ && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
+ && brightness < 0;
mAutomaticBrightnessController.configure(autoBrightnessEnabled,
- mPowerRequest.screenAutoBrightnessAdjustment);
+ mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON);
}
// Apply auto-brightness.
@@ -612,6 +621,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAppliedAutoBrightness = false;
}
+ // Use default brightness when dozing unless overridden.
+ if (brightness < 0 && (state == Display.STATE_DOZE
+ || state == Display.STATE_DOZE_SUSPEND)) {
+ brightness = mScreenBrightnessDozeConfig;
+ }
+
// Apply manual brightness.
// Use the current brightness setting from the request, which is expected
// provide a nominal default value for the case where auto-brightness
@@ -1024,6 +1039,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
pw.println(" mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
+ pw.println(" mAllowAutoBrightnessWhileDozingConfig=" +
+ mAllowAutoBrightnessWhileDozingConfig);
pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig);
mHandler.runWithScissors(new Runnable() {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 6bae761..f0f7973 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1029,6 +1029,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
OneTouchRecordAction action = actions.get(0);
if (action.getRecorderAddress() != message.getSource()) {
announceOneTouchRecordResult(
+ message.getSource(),
HdmiControlManager.ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS);
}
return super.handleRecordTvScreen(message);
@@ -1047,20 +1048,20 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
protected boolean handleTimerClearedStatus(HdmiCecMessage message) {
byte[] params = message.getParams();
int timerClearedStatusData = params[0] & 0xFF;
- announceTimerRecordingResult(timerClearedStatusData);
+ announceTimerRecordingResult(message.getSource(), timerClearedStatusData);
return true;
}
- void announceOneTouchRecordResult(int result) {
- mService.invokeOneTouchRecordResult(result);
+ void announceOneTouchRecordResult(int recorderAddress, int result) {
+ mService.invokeOneTouchRecordResult(recorderAddress, result);
}
- void announceTimerRecordingResult(int result) {
- mService.invokeTimerRecordingResult(result);
+ void announceTimerRecordingResult(int recorderAddress, int result) {
+ mService.invokeTimerRecordingResult(recorderAddress, result);
}
- void announceClearTimerRecordingResult(int result) {
- mService.invokeClearTimerRecordingResult(result);
+ void announceClearTimerRecordingResult(int recorderAddress, int result) {
+ mService.invokeClearTimerRecordingResult(recorderAddress, result);
}
private boolean isMessageForSystemAudio(HdmiCecMessage message) {
@@ -1528,19 +1529,21 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
assertRunOnServiceThread();
if (!mService.isControlEnabled()) {
Slog.w(TAG, "Can not start one touch record. CEC control is disabled.");
- announceOneTouchRecordResult(ONE_TOUCH_RECORD_CEC_DISABLED);
+ announceOneTouchRecordResult(recorderAddress, ONE_TOUCH_RECORD_CEC_DISABLED);
return Constants.ABORT_NOT_IN_CORRECT_MODE;
}
if (!checkRecorder(recorderAddress)) {
Slog.w(TAG, "Invalid recorder address:" + recorderAddress);
- announceOneTouchRecordResult(ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
+ announceOneTouchRecordResult(recorderAddress,
+ ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
return Constants.ABORT_NOT_IN_CORRECT_MODE;
}
if (!checkRecordSource(recordSource)) {
Slog.w(TAG, "Invalid record source." + Arrays.toString(recordSource));
- announceOneTouchRecordResult(ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN);
+ announceOneTouchRecordResult(recorderAddress,
+ ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN);
return Constants.ABORT_UNABLE_TO_DETERMINE;
}
@@ -1555,13 +1558,14 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
assertRunOnServiceThread();
if (!mService.isControlEnabled()) {
Slog.w(TAG, "Can not stop one touch record. CEC control is disabled.");
- announceOneTouchRecordResult(ONE_TOUCH_RECORD_CEC_DISABLED);
+ announceOneTouchRecordResult(recorderAddress, ONE_TOUCH_RECORD_CEC_DISABLED);
return;
}
if (!checkRecorder(recorderAddress)) {
Slog.w(TAG, "Invalid recorder address:" + recorderAddress);
- announceOneTouchRecordResult(ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
+ announceOneTouchRecordResult(recorderAddress,
+ ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
return;
}
@@ -1587,13 +1591,14 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
assertRunOnServiceThread();
if (!mService.isControlEnabled()) {
Slog.w(TAG, "Can not start one touch record. CEC control is disabled.");
- announceTimerRecordingResult(TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED);
+ announceTimerRecordingResult(recorderAddress,
+ TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED);
return;
}
if (!checkRecorder(recorderAddress)) {
Slog.w(TAG, "Invalid recorder address:" + recorderAddress);
- announceTimerRecordingResult(
+ announceTimerRecordingResult(recorderAddress,
TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
return;
}
@@ -1601,6 +1606,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
if (!checkTimerRecordingSource(sourceType, recordSource)) {
Slog.w(TAG, "Invalid record source." + Arrays.toString(recordSource));
announceTimerRecordingResult(
+ recorderAddress,
TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE);
return;
}
@@ -1621,26 +1627,29 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
assertRunOnServiceThread();
if (!mService.isControlEnabled()) {
Slog.w(TAG, "Can not start one touch record. CEC control is disabled.");
- announceClearTimerRecordingResult(CLEAR_TIMER_STATUS_CEC_DISABLE);
+ announceClearTimerRecordingResult(recorderAddress, CLEAR_TIMER_STATUS_CEC_DISABLE);
return;
}
if (!checkRecorder(recorderAddress)) {
Slog.w(TAG, "Invalid recorder address:" + recorderAddress);
- announceClearTimerRecordingResult(CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION);
+ announceClearTimerRecordingResult(recorderAddress,
+ CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION);
return;
}
if (!checkTimerRecordingSource(sourceType, recordSource)) {
Slog.w(TAG, "Invalid record source." + Arrays.toString(recordSource));
- announceClearTimerRecordingResult(CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE);
+ announceClearTimerRecordingResult(recorderAddress,
+ CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE);
return;
}
sendClearTimerMessage(recorderAddress, sourceType, recordSource);
}
- private void sendClearTimerMessage(int recorderAddress, int sourceType, byte[] recordSource) {
+ private void sendClearTimerMessage(final int recorderAddress, int sourceType,
+ byte[] recordSource) {
HdmiCecMessage message = null;
switch (sourceType) {
case TIMER_RECORDING_TYPE_DIGITAL:
@@ -1657,7 +1666,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
break;
default:
Slog.w(TAG, "Invalid source type:" + recorderAddress);
- announceClearTimerRecordingResult(CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE);
+ announceClearTimerRecordingResult(recorderAddress,
+ CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE);
return;
}
@@ -1665,7 +1675,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@Override
public void onSendCompleted(int error) {
if (error != Constants.SEND_RESULT_SUCCESS) {
- announceClearTimerRecordingResult(
+ announceClearTimerRecordingResult(recorderAddress,
CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE);
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index d703989..53740fe 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -29,11 +29,16 @@ public final class HdmiCecMessageValidator {
static final int ERROR_SOURCE = 1;
static final int ERROR_DESTINATION = 2;
static final int ERROR_PARAMETER = 3;
+ static final int ERROR_PARAMETER_SHORT = 4;
private final HdmiControlService mService;
interface ParameterValidator {
- boolean isValid(byte[] params);
+ /**
+ * @return errorCode errorCode can be {@link #OK}, {@link #ERROR_PARAMETER} or
+ * {@link #ERROR_PARAMETER_SHORT}.
+ */
+ int isValid(byte[] params);
}
// Only the direct addressing is allowed.
@@ -74,7 +79,7 @@ public final class HdmiCecMessageValidator {
addValidationInfo(Constants.MESSAGE_SET_STREAM_PATH,
physicalAddressValidator, DEST_BROADCAST);
addValidationInfo(Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST,
- physicalAddressValidator, DEST_DIRECT);
+ new SystemAudioModeRequestValidator(), DEST_DIRECT);
// Messages have no parameter.
FixedLengthValidator noneValidator = new FixedLengthValidator(0);
@@ -213,9 +218,10 @@ public final class HdmiCecMessageValidator {
}
// Check the parameter type.
- if (!info.parameterValidator.isValid(message.getParams())) {
+ int errorCode = info.parameterValidator.isValid(message.getParams());
+ if (errorCode != OK) {
HdmiLogger.warning("Unexpected parameters: " + message);
- return ERROR_PARAMETER;
+ return errorCode;
}
return OK;
}
@@ -228,8 +234,10 @@ public final class HdmiCecMessageValidator {
}
@Override
- public boolean isValid(byte[] params) {
- return params.length == mLength;
+ public int isValid(byte[] params) {
+ // If the length is longer than expected, we assume it's OK since the parameter can be
+ // extended in the future version.
+ return params.length < mLength ? ERROR_PARAMETER_SHORT : OK;
}
}
@@ -243,8 +251,8 @@ public final class HdmiCecMessageValidator {
}
@Override
- public boolean isValid(byte[] params) {
- return params.length >= mMinLength && params.length <= mMaxLength;
+ public int isValid(byte[] params) {
+ return params.length < mMinLength ? ERROR_PARAMETER_SHORT : OK;
}
}
@@ -270,8 +278,7 @@ public final class HdmiCecMessageValidator {
* Check if the given type is valid. A valid type is one of the actual logical device types
* defined in the standard ({@link HdmiDeviceInfo#DEVICE_TV},
* {@link HdmiDeviceInfo#DEVICE_PLAYBACK}, {@link HdmiDeviceInfo#DEVICE_TUNER},
- * {@link HdmiDeviceInfo#DEVICE_RECORDER}, and
- * {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM}).
+ * {@link HdmiDeviceInfo#DEVICE_RECORDER}, and {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM}).
*
* @param type device type
* @return true if the given type is valid
@@ -282,33 +289,49 @@ public final class HdmiCecMessageValidator {
&& type != HdmiDeviceInfo.DEVICE_RESERVED;
}
+ private static int toErrorCode(boolean success) {
+ return success ? OK : ERROR_PARAMETER;
+ }
+
private class PhysicalAddressValidator implements ParameterValidator {
@Override
- public boolean isValid(byte[] params) {
- if (params.length != 2) {
- return false;
+ public int isValid(byte[] params) {
+ if (params.length < 2) {
+ return ERROR_PARAMETER_SHORT;
+ }
+ return toErrorCode(isValidPhysicalAddress(params, 0));
+ }
+ }
+
+ private class SystemAudioModeRequestValidator extends PhysicalAddressValidator {
+ @Override
+ public int isValid(byte[] params) {
+ // TV can send <System Audio Mode Request> with no parameters to terminate system audio.
+ if (params.length == 0) {
+ return OK;
}
- return isValidPhysicalAddress(params, 0);
+ return super.isValid(params);
}
}
private class ReportPhysicalAddressValidator implements ParameterValidator {
@Override
- public boolean isValid(byte[] params) {
- if (params.length != 3) {
- return false;
+ public int isValid(byte[] params) {
+ if (params.length < 3) {
+ return ERROR_PARAMETER_SHORT;
}
- return isValidPhysicalAddress(params, 0) && isValidType(params[2]);
+ return toErrorCode(isValidPhysicalAddress(params, 0) && isValidType(params[2]));
}
}
private class RoutingChangeValidator implements ParameterValidator {
@Override
- public boolean isValid(byte[] params) {
- if (params.length != 4) {
- return false;
+ public int isValid(byte[] params) {
+ if (params.length < 4) {
+ return ERROR_PARAMETER_SHORT;
}
- return isValidPhysicalAddress(params, 0) && isValidPhysicalAddress(params, 2);
+ return toErrorCode(
+ isValidPhysicalAddress(params, 0) && isValidPhysicalAddress(params, 2));
}
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index aeb21db..907a49a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -719,7 +719,8 @@ public final class HdmiControlService extends SystemService {
assertRunOnServiceThread();
int errorCode = mMessageValidator.isValid(message);
if (errorCode != HdmiCecMessageValidator.OK) {
- // We'll not response on the messages with the invalid source or destination.
+ // We'll not response on the messages with the invalid source or destination
+ // or with parameter length shorter than specified in the standard.
if (errorCode == HdmiCecMessageValidator.ERROR_PARAMETER) {
maySendFeatureAbortCommand(message, Constants.ABORT_INVALID_OPERAND);
}
@@ -1661,11 +1662,11 @@ public final class HdmiControlService extends SystemService {
}
}
- void invokeOneTouchRecordResult(int result) {
+ void invokeOneTouchRecordResult(int recorderAddress, int result) {
synchronized (mLock) {
if (mRecordListenerRecord != null) {
try {
- mRecordListenerRecord.mListener.onOneTouchRecordResult(result);
+ mRecordListenerRecord.mListener.onOneTouchRecordResult(recorderAddress, result);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onOneTouchRecordResult.", e);
}
@@ -1673,11 +1674,11 @@ public final class HdmiControlService extends SystemService {
}
}
- void invokeTimerRecordingResult(int result) {
+ void invokeTimerRecordingResult(int recorderAddress, int result) {
synchronized (mLock) {
if (mRecordListenerRecord != null) {
try {
- mRecordListenerRecord.mListener.onTimerRecordingResult(result);
+ mRecordListenerRecord.mListener.onTimerRecordingResult(recorderAddress, result);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onTimerRecordingResult.", e);
}
@@ -1685,11 +1686,12 @@ public final class HdmiControlService extends SystemService {
}
}
- void invokeClearTimerRecordingResult(int result) {
+ void invokeClearTimerRecordingResult(int recorderAddress, int result) {
synchronized (mLock) {
if (mRecordListenerRecord != null) {
try {
- mRecordListenerRecord.mListener.onClearTimerRecordingResult(result);
+ mRecordListenerRecord.mListener.onClearTimerRecordingResult(recorderAddress,
+ result);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onClearTimerRecordingResult.", e);
}
diff --git a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
index 906944b..d80b81f 100644
--- a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
+++ b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
@@ -64,6 +64,7 @@ public class OneTouchRecordAction extends HdmiCecFeatureAction {
// if failed to send <Record On>, display error message and finish action.
if (error != Constants.SEND_RESULT_SUCCESS) {
tv().announceOneTouchRecordResult(
+ mRecorderAddress,
ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
finish();
return;
@@ -94,7 +95,7 @@ public class OneTouchRecordAction extends HdmiCecFeatureAction {
}
int recordStatus = cmd.getParams()[0];
- tv().announceOneTouchRecordResult(recordStatus);
+ tv().announceOneTouchRecordResult(mRecorderAddress, recordStatus);
Slog.i(TAG, "Got record status:" + recordStatus + " from " + cmd.getSource());
// If recording started successfully, change state and keep this action until <Record Off>
@@ -121,7 +122,8 @@ public class OneTouchRecordAction extends HdmiCecFeatureAction {
return;
}
- tv().announceOneTouchRecordResult(ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
+ tv().announceOneTouchRecordResult(mRecorderAddress,
+ ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
finish();
}
diff --git a/services/core/java/com/android/server/hdmi/TimerRecordingAction.java b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java
index 5fcbc91..16fc25f 100644
--- a/services/core/java/com/android/server/hdmi/TimerRecordingAction.java
+++ b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java
@@ -74,7 +74,7 @@ public class TimerRecordingAction extends HdmiCecFeatureAction {
mRecorderAddress, mRecordSource);
break;
default:
- tv().announceTimerRecordingResult(
+ tv().announceTimerRecordingResult(mRecorderAddress,
TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE);
finish();
return;
@@ -83,7 +83,7 @@ public class TimerRecordingAction extends HdmiCecFeatureAction {
@Override
public void onSendCompleted(int error) {
if (error != Constants.SEND_RESULT_SUCCESS) {
- tv().announceTimerRecordingResult(
+ tv().announceTimerRecordingResult(mRecorderAddress,
TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
finish();
return;
@@ -114,7 +114,7 @@ public class TimerRecordingAction extends HdmiCecFeatureAction {
byte[] timerStatusData = cmd.getParams();
// [Timer Status Data] should be one or three bytes.
if (timerStatusData.length == 1 || timerStatusData.length == 3) {
- tv().announceTimerRecordingResult(bytesToInt(timerStatusData));
+ tv().announceTimerRecordingResult(mRecorderAddress, bytesToInt(timerStatusData));
Slog.i(TAG, "Received [Timer Status Data]:" + Arrays.toString(timerStatusData));
} else {
Slog.w(TAG, "Invalid [Timer Status Data]:" + Arrays.toString(timerStatusData));
@@ -138,7 +138,8 @@ public class TimerRecordingAction extends HdmiCecFeatureAction {
}
int reason = params[1] & 0xFF;
Slog.i(TAG, "[Feature Abort] for " + messageType + " reason:" + reason);
- tv().announceTimerRecordingResult(TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
+ tv().announceTimerRecordingResult(mRecorderAddress,
+ TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
finish();
return true;
}
@@ -163,7 +164,8 @@ public class TimerRecordingAction extends HdmiCecFeatureAction {
return;
}
- tv().announceTimerRecordingResult(TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
+ tv().announceTimerRecordingResult(mRecorderAddress,
+ TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
finish();
}
}
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 05ad1fe..3ff9ff4 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -52,6 +52,7 @@ public class ConditionProviders extends ManagedServices {
private final ArrayList<ConditionRecord> mRecords = new ArrayList<ConditionRecord>();
private final CountdownConditionProvider mCountdown = new CountdownConditionProvider();
private final DowntimeConditionProvider mDowntime = new DowntimeConditionProvider();
+ private final NextAlarmConditionProvider mNextAlarm = new NextAlarmConditionProvider();
private Condition mExitCondition;
private ComponentName mExitConditionComponent;
@@ -99,6 +100,7 @@ public class ConditionProviders extends ManagedServices {
}
mCountdown.dump(pw, filter);
mDowntime.dump(pw, filter);
+ mNextAlarm.dump(pw, filter);
}
@Override
@@ -116,6 +118,23 @@ public class ConditionProviders extends ManagedServices {
registerService(mDowntime.asInterface(), DowntimeConditionProvider.COMPONENT,
UserHandle.USER_OWNER);
mDowntime.setCallback(new DowntimeCallback());
+ mNextAlarm.attachBase(mContext);
+ registerService(mNextAlarm.asInterface(), NextAlarmConditionProvider.COMPONENT,
+ UserHandle.USER_OWNER);
+ mNextAlarm.setCallback(new NextAlarmConditionProvider.Callback() {
+ @Override
+ public boolean isInDowntime() {
+ return mDowntime.isInDowntime();
+ }
+ });
+ }
+
+ @Override
+ public void onUserSwitched() {
+ super.onUserSwitched();
+ if (mNextAlarm != null) {
+ mNextAlarm.onUserSwitched();
+ }
}
@Override
@@ -534,20 +553,22 @@ public class ConditionProviders extends ManagedServices {
private class DowntimeCallback implements DowntimeConditionProvider.Callback {
@Override
- public void onDowntimeChanged(boolean inDowntime) {
+ public void onDowntimeChanged(int downtimeMode) {
final int mode = mZenModeHelper.getZenMode();
final ZenModeConfig config = mZenModeHelper.getConfig();
- // enter downtime
- if (inDowntime && mode == Global.ZEN_MODE_OFF && config != null) {
+ final boolean inDowntime = downtimeMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+ || downtimeMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+ final boolean downtimeCurrent = mDowntime.isDowntimeCondition(mExitCondition);
+ // enter downtime, or update mode if reconfigured during an active downtime
+ if (inDowntime && (mode == Global.ZEN_MODE_OFF || downtimeCurrent) && config != null) {
final Condition condition = mDowntime.createCondition(config.toDowntimeInfo(),
Condition.STATE_TRUE);
- mZenModeHelper.setZenMode(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, "downtimeEnter");
+ mZenModeHelper.setZenMode(downtimeMode, "downtimeEnter");
setZenModeCondition(condition, "downtime");
}
// exit downtime
- if (!inDowntime && mDowntime.isDowntimeCondition(mExitCondition)
- && (mode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
- || mode == Global.ZEN_MODE_NO_INTERRUPTIONS)) {
+ if (!inDowntime && downtimeCurrent && (mode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+ || mode == Global.ZEN_MODE_NO_INTERRUPTIONS)) {
mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF, "downtimeExit");
}
}
diff --git a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
index efe47c3..881c9ad 100644
--- a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
+++ b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
+import android.provider.Settings.Global;
import android.service.notification.Condition;
import android.service.notification.ConditionProviderService;
import android.service.notification.IConditionProvider;
@@ -64,7 +65,7 @@ public class DowntimeConditionProvider extends ConditionProviderService {
private final ArraySet<Integer> mDays = new ArraySet<Integer>();
private boolean mConnected;
- private boolean mInDowntime;
+ private int mDowntimeMode;
private ZenModeConfig mConfig;
private Callback mCallback;
@@ -75,7 +76,7 @@ public class DowntimeConditionProvider extends ConditionProviderService {
public void dump(PrintWriter pw, DumpFilter filter) {
pw.println(" DowntimeConditionProvider:");
pw.print(" mConnected="); pw.println(mConnected);
- pw.print(" mInDowntime="); pw.println(mInDowntime);
+ pw.print(" mDowntimeMode="); pw.println(Global.zenModeToString(mDowntimeMode));
}
public void attachBase(Context base) {
@@ -113,7 +114,7 @@ public class DowntimeConditionProvider extends ConditionProviderService {
public void onRequestConditions(int relevance) {
if (DEBUG) Slog.d(TAG, "onRequestConditions relevance=" + relevance);
if ((relevance & Condition.FLAG_RELEVANT_NOW) != 0) {
- if (mInDowntime && mConfig != null) {
+ if (isInDowntime() && mConfig != null) {
notifyCondition(createCondition(mConfig.toDowntimeInfo(), Condition.STATE_TRUE));
}
}
@@ -124,7 +125,7 @@ public class DowntimeConditionProvider extends ConditionProviderService {
if (DEBUG) Slog.d(TAG, "onSubscribe conditionId=" + conditionId);
final DowntimeInfo downtime = ZenModeConfig.tryParseDowntimeConditionId(conditionId);
if (downtime != null && mConfig != null) {
- final int state = mConfig.toDowntimeInfo().equals(downtime) && mInDowntime
+ final int state = mConfig.toDowntimeInfo().equals(downtime) && isInDowntime()
? Condition.STATE_TRUE : Condition.STATE_FALSE;
if (DEBUG) Slog.d(TAG, "notify condition state: " + Condition.stateToString(state));
notifyCondition(createCondition(downtime, state));
@@ -146,7 +147,7 @@ public class DowntimeConditionProvider extends ConditionProviderService {
}
public boolean isInDowntime() {
- return mInDowntime;
+ return mDowntimeMode != Global.ZEN_MODE_OFF;
}
public Condition createCondition(DowntimeInfo downtime, int state) {
@@ -158,7 +159,8 @@ public class DowntimeConditionProvider extends ConditionProviderService {
final long time = getTime(System.currentTimeMillis(), downtime.endHour, downtime.endMinute);
final String formatted = new SimpleDateFormat(pattern, locale).format(new Date(time));
final String summary = mContext.getString(R.string.downtime_condition_summary, formatted);
- return new Condition(id, summary, "", "", 0, state, Condition.FLAG_RELEVANT_NOW);
+ final String line1 = mContext.getString(R.string.downtime_condition_line_one);
+ return new Condition(id, summary, line1, formatted, 0, state, Condition.FLAG_RELEVANT_NOW);
}
public boolean isDowntimeCondition(Condition condition) {
@@ -181,15 +183,18 @@ public class DowntimeConditionProvider extends ConditionProviderService {
}
}
- private boolean isInDowntime(long time) {
- if (mConfig == null || mDays.size() == 0) return false;
+ private int computeDowntimeMode(long time) {
+ if (mConfig == null || mDays.size() == 0) return Global.ZEN_MODE_OFF;
final long start = getTime(time, mConfig.sleepStartHour, mConfig.sleepStartMinute);
long end = getTime(time, mConfig.sleepEndHour, mConfig.sleepEndMinute);
- if (start == end) return false;
+ if (start == end) return Global.ZEN_MODE_OFF;
if (end < start) {
end = addDays(end, 1);
}
- return isInDowntime(-1, time, start, end) || isInDowntime(0, time, start, end);
+ final boolean inDowntime = isInDowntime(-1, time, start, end)
+ || isInDowntime(0, time, start, end);
+ return inDowntime ? (mConfig.sleepNone ? Global.ZEN_MODE_NO_INTERRUPTIONS
+ : Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) : Global.ZEN_MODE_OFF;
}
private boolean isInDowntime(int daysOffset, long time, long start, long end) {
@@ -201,18 +206,18 @@ public class DowntimeConditionProvider extends ConditionProviderService {
}
private void reevaluateDowntime() {
- final boolean inDowntime = isInDowntime(System.currentTimeMillis());
- if (DEBUG) Slog.d(TAG, "inDowntime=" + inDowntime);
- if (inDowntime == mInDowntime) return;
- Slog.i(TAG, (inDowntime ? "Entering" : "Exiting" ) + " downtime");
- mInDowntime = inDowntime;
- ZenLog.traceDowntime(mInDowntime, getDayOfWeek(System.currentTimeMillis()), mDays);
+ final int downtimeMode = computeDowntimeMode(System.currentTimeMillis());
+ if (DEBUG) Slog.d(TAG, "downtimeMode=" + downtimeMode);
+ if (downtimeMode == mDowntimeMode) return;
+ mDowntimeMode = downtimeMode;
+ Slog.i(TAG, (isInDowntime() ? "Entering" : "Exiting" ) + " downtime");
+ ZenLog.traceDowntime(mDowntimeMode, getDayOfWeek(System.currentTimeMillis()), mDays);
fireDowntimeChanged();
}
private void fireDowntimeChanged() {
if (mCallback != null) {
- mCallback.onDowntimeChanged(mInDowntime);
+ mCallback.onDowntimeChanged(mDowntimeMode);
}
}
@@ -255,7 +260,10 @@ public class DowntimeConditionProvider extends ConditionProviderService {
time = addDays(time, 1);
}
final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, requestCode,
- new Intent(action).putExtra(EXTRA_TIME, time), PendingIntent.FLAG_UPDATE_CURRENT);
+ new Intent(action)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ .putExtra(EXTRA_TIME, time),
+ PendingIntent.FLAG_UPDATE_CURRENT);
alarms.cancel(pendingIntent);
if (mConfig.sleepMode != null) {
if (DEBUG) Slog.d(TAG, String.format("Scheduling %s for %s, %s in the future, now=%s",
@@ -289,6 +297,6 @@ public class DowntimeConditionProvider extends ConditionProviderService {
};
public interface Callback {
- void onDowntimeChanged(boolean inDowntime);
+ void onDowntimeChanged(int downtimeMode);
}
}
diff --git a/services/core/java/com/android/server/notification/NextAlarmConditionProvider.java b/services/core/java/com/android/server/notification/NextAlarmConditionProvider.java
new file mode 100644
index 0000000..4a29573
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NextAlarmConditionProvider.java
@@ -0,0 +1,353 @@
+/*
+ * 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.server.notification;
+
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.AlarmManager.AlarmClockInfo;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.service.notification.Condition;
+import android.service.notification.ConditionProviderService;
+import android.service.notification.IConditionProvider;
+import android.service.notification.ZenModeConfig;
+import android.util.TimeUtils;
+import android.text.format.DateFormat;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.server.notification.NotificationManagerService.DumpFilter;
+
+import java.io.PrintWriter;
+import java.util.Locale;
+
+/**
+ * Built-in zen condition provider for alarm-clock-based conditions.
+ *
+ * <p>If the user's next alarm is within a lookahead threshold (config, default 12hrs), advertise
+ * it as an exit condition for zen mode (unless the built-in downtime condition is also available).
+ *
+ * <p>When this next alarm is selected as the active exit condition, follow subsequent changes
+ * to the user's next alarm, assuming it remains within the 12-hr window.
+ *
+ * <p>The next alarm is defined as {@link AlarmManager#getNextAlarmClock(int)}, which does not
+ * survive a reboot. Maintain the illusion of a consistent next alarm value by holding on to
+ * a persisted condition until we receive the first value after reboot, or timeout with no value.
+ */
+public class NextAlarmConditionProvider extends ConditionProviderService {
+ private static final String TAG = "NextAlarmConditions";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final String ACTION_TRIGGER = TAG + ".trigger";
+ private static final String EXTRA_TRIGGER = "trigger";
+ private static final int REQUEST_CODE = 100;
+ private static final long SECONDS = 1000;
+ private static final long MINUTES = 60 * SECONDS;
+ private static final long HOURS = 60 * MINUTES;
+ private static final long NEXT_ALARM_UPDATE_DELAY = 1 * SECONDS; // treat clear+set as update
+ private static final long EARLY = 5 * SECONDS; // fire early, ensure alarm stream is unmuted
+ private static final long WAIT_AFTER_CONNECT = 5 * MINUTES;// for initial alarm re-registration
+ private static final long WAIT_AFTER_BOOT = 20 * SECONDS; // for initial alarm re-registration
+ private static final String NEXT_ALARM_PATH = "next_alarm";
+ public static final ComponentName COMPONENT =
+ new ComponentName("android", NextAlarmConditionProvider.class.getName());
+
+ private final Context mContext = this;
+ private final H mHandler = new H();
+
+ private long mConnected;
+ private boolean mRegistered;
+ private AlarmManager mAlarmManager;
+ private int mCurrentUserId;
+ private long mLookaheadThreshold;
+ private long mScheduledAlarmTime;
+ private Callback mCallback;
+ private Uri mCurrentSubscription;
+ private PowerManager.WakeLock mWakeLock;
+ private long mBootCompleted;
+
+ public NextAlarmConditionProvider() {
+ if (DEBUG) Slog.d(TAG, "new NextAlarmConditionProvider()");
+ }
+
+ public void dump(PrintWriter pw, DumpFilter filter) {
+ pw.println(" NextAlarmConditionProvider:");
+ pw.print(" mConnected="); pw.println(mConnected);
+ pw.print(" mBootCompleted="); pw.println(mBootCompleted);
+ pw.print(" mRegistered="); pw.println(mRegistered);
+ pw.print(" mCurrentUserId="); pw.println(mCurrentUserId);
+ pw.print(" mScheduledAlarmTime="); pw.println(formatAlarmDebug(mScheduledAlarmTime));
+ pw.print(" mLookaheadThreshold="); pw.print(mLookaheadThreshold);
+ pw.print(" ("); TimeUtils.formatDuration(mLookaheadThreshold, pw); pw.println(")");
+ pw.print(" mCurrentSubscription="); pw.println(mCurrentSubscription);
+ pw.print(" mWakeLock="); pw.println(mWakeLock);
+ }
+
+ public void setCallback(Callback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void onConnected() {
+ if (DEBUG) Slog.d(TAG, "onConnected");
+ mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ final PowerManager p = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = p.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ mLookaheadThreshold = mContext.getResources()
+ .getInteger(R.integer.config_next_alarm_condition_lookahead_threshold_hrs) * HOURS;
+ init();
+ mConnected = System.currentTimeMillis();
+ }
+
+ public void onUserSwitched() {
+ if (DEBUG) Slog.d(TAG, "onUserSwitched");
+ if (mConnected != 0) {
+ init();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (DEBUG) Slog.d(TAG, "onDestroy");
+ if (mRegistered) {
+ mContext.unregisterReceiver(mReceiver);
+ mRegistered = false;
+ }
+ mConnected = 0;
+ }
+
+ @Override
+ public void onRequestConditions(int relevance) {
+ if (mConnected == 0 || (relevance & Condition.FLAG_RELEVANT_NOW) == 0) return;
+
+ final AlarmClockInfo nextAlarm = mAlarmManager.getNextAlarmClock(mCurrentUserId);
+ if (nextAlarm == null) return; // no next alarm
+ if (mCallback != null && mCallback.isInDowntime()) return; // prefer downtime condition
+ if (!isWithinLookaheadThreshold(nextAlarm)) return; // alarm not within window
+
+ // next alarm exists, and is within the configured lookahead threshold
+ notifyCondition(newConditionId(), nextAlarm, Condition.STATE_TRUE, "request");
+ }
+
+ private boolean isWithinLookaheadThreshold(AlarmClockInfo alarm) {
+ if (alarm == null) return false;
+ final long delta = getEarlyTriggerTime(alarm) - System.currentTimeMillis();
+ return delta > 0 && (mLookaheadThreshold <= 0 || delta < mLookaheadThreshold);
+ }
+
+ @Override
+ public void onSubscribe(Uri conditionId) {
+ if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
+ if (!isNextAlarmCondition(conditionId)) {
+ notifyCondition(conditionId, null, Condition.STATE_FALSE, "badCondition");
+ return;
+ }
+ mCurrentSubscription = conditionId;
+ mHandler.postEvaluate(0);
+ }
+
+ private static long getEarlyTriggerTime(AlarmClockInfo alarm) {
+ return alarm != null ? (alarm.getTriggerTime() - EARLY) : 0;
+ }
+
+ private boolean isDoneWaitingAfterBoot(long time) {
+ if (mBootCompleted > 0) return (time - mBootCompleted) > WAIT_AFTER_BOOT;
+ if (mConnected > 0) return (time - mConnected) > WAIT_AFTER_CONNECT;
+ return true;
+ }
+
+ private void handleEvaluate() {
+ final AlarmClockInfo nextAlarm = mAlarmManager.getNextAlarmClock(mCurrentUserId);
+ final long triggerTime = getEarlyTriggerTime(nextAlarm);
+ final boolean withinThreshold = isWithinLookaheadThreshold(nextAlarm);
+ final long now = System.currentTimeMillis();
+ final boolean booted = isDoneWaitingAfterBoot(now);
+ if (DEBUG) Slog.d(TAG, "handleEvaluate mCurrentSubscription=" + mCurrentSubscription
+ + " nextAlarm=" + formatAlarmDebug(triggerTime)
+ + " withinThreshold=" + withinThreshold
+ + " booted=" + booted);
+ if (mCurrentSubscription == null) return; // no one cares
+ if (!booted) {
+ // we don't know yet
+ notifyCondition(mCurrentSubscription, nextAlarm, Condition.STATE_UNKNOWN, "!booted");
+ final long recheckTime = (mBootCompleted > 0 ? mBootCompleted : now) + WAIT_AFTER_BOOT;
+ rescheduleAlarm(recheckTime);
+ return;
+ }
+ if (!withinThreshold) {
+ // triggertime invalid or in the past, condition = false
+ notifyCondition(mCurrentSubscription, nextAlarm, Condition.STATE_FALSE, "!within");
+ mCurrentSubscription = null;
+ return;
+ }
+ // triggertime in the future, condition = true, schedule alarm
+ notifyCondition(mCurrentSubscription, nextAlarm, Condition.STATE_TRUE, "within");
+ rescheduleAlarm(triggerTime);
+ }
+
+ private static String formatDuration(long millis) {
+ final StringBuilder sb = new StringBuilder();
+ TimeUtils.formatDuration(millis, sb);
+ return sb.toString();
+ }
+
+ private void rescheduleAlarm(long time) {
+ if (DEBUG) Slog.d(TAG, "rescheduleAlarm " + time);
+ final AlarmManager alarms = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, REQUEST_CODE,
+ new Intent(ACTION_TRIGGER)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ .putExtra(EXTRA_TRIGGER, time),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ alarms.cancel(pendingIntent);
+ mScheduledAlarmTime = time;
+ if (time > 0) {
+ if (DEBUG) Slog.d(TAG, String.format("Scheduling alarm for %s (in %s)",
+ formatAlarmDebug(time), formatDuration(time - System.currentTimeMillis())));
+ alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
+ }
+ }
+
+ private void notifyCondition(Uri id, AlarmClockInfo alarm, int state, String reason) {
+ final String formattedAlarm = alarm == null ? "" : formatAlarm(alarm.getTriggerTime());
+ if (DEBUG) Slog.d(TAG, "notifyCondition " + Condition.stateToString(state)
+ + " alarm=" + formattedAlarm + " reason=" + reason);
+ notifyCondition(new Condition(id,
+ mContext.getString(R.string.zen_mode_next_alarm_summary, formattedAlarm),
+ mContext.getString(R.string.zen_mode_next_alarm_line_one),
+ formattedAlarm, 0, state, Condition.FLAG_RELEVANT_NOW));
+ }
+
+ @Override
+ public void onUnsubscribe(Uri conditionId) {
+ if (DEBUG) Slog.d(TAG, "onUnsubscribe " + conditionId);
+ if (conditionId != null && conditionId.equals(mCurrentSubscription)) {
+ mCurrentSubscription = null;
+ rescheduleAlarm(0);
+ }
+ }
+
+ public void attachBase(Context base) {
+ attachBaseContext(base);
+ }
+
+ public IConditionProvider asInterface() {
+ return (IConditionProvider) onBind(null);
+ }
+
+ private Uri newConditionId() {
+ return new Uri.Builder().scheme(Condition.SCHEME)
+ .authority(ZenModeConfig.SYSTEM_AUTHORITY)
+ .appendPath(NEXT_ALARM_PATH)
+ .appendPath(Integer.toString(mCurrentUserId))
+ .build();
+ }
+
+ private boolean isNextAlarmCondition(Uri conditionId) {
+ return conditionId != null && conditionId.getScheme().equals(Condition.SCHEME)
+ && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY)
+ && conditionId.getPathSegments().size() == 2
+ && conditionId.getPathSegments().get(0).equals(NEXT_ALARM_PATH)
+ && conditionId.getPathSegments().get(1).equals(Integer.toString(mCurrentUserId));
+ }
+
+ private void init() {
+ if (mRegistered) {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ mCurrentUserId = ActivityManager.getCurrentUser();
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
+ filter.addAction(ACTION_TRIGGER);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ mContext.registerReceiverAsUser(mReceiver, new UserHandle(mCurrentUserId), filter, null,
+ null);
+ mRegistered = true;
+ mHandler.postEvaluate(0);
+ }
+
+ private String formatAlarm(long time) {
+ return formatAlarm(time, "Hm", "hma");
+ }
+
+ private String formatAlarm(long time, String skeleton24, String skeleton12) {
+ final String skeleton = DateFormat.is24HourFormat(mContext) ? skeleton24 : skeleton12;
+ final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
+ return DateFormat.format(pattern, time).toString();
+ }
+
+ private String formatAlarmDebug(AlarmClockInfo alarm) {
+ return formatAlarmDebug(alarm != null ? alarm.getTriggerTime() : 0);
+ }
+
+ private String formatAlarmDebug(long time) {
+ if (time <= 0) return Long.toString(time);
+ return String.format("%s (%s)", time, formatAlarm(time, "Hms", "hmsa"));
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (DEBUG) Slog.d(TAG, "onReceive " + action);
+ long delay = 0;
+ if (action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
+ delay = NEXT_ALARM_UPDATE_DELAY;
+ if (DEBUG) Slog.d(TAG, String.format(" next alarm for user %s: %s",
+ mCurrentUserId,
+ formatAlarmDebug(mAlarmManager.getNextAlarmClock(mCurrentUserId))));
+ } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
+ mBootCompleted = System.currentTimeMillis();
+ }
+ mHandler.postEvaluate(delay);
+ mWakeLock.acquire(delay + 5000); // stay awake during evaluate
+ }
+ };
+
+ public interface Callback {
+ boolean isInDowntime();
+ }
+
+ private class H extends Handler {
+ private static final int MSG_EVALUATE = 1;
+
+ public void postEvaluate(long delay) {
+ removeMessages(MSG_EVALUATE);
+ sendEmptyMessageDelayed(MSG_EVALUATE, delay);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_EVALUATE) {
+ handleEvaluate();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index e0b83de..1a3da79 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -75,8 +75,8 @@ public class ZenLog {
append(TYPE_SET_RINGER_MODE, ringerModeToString(ringerMode));
}
- public static void traceDowntime(boolean inDowntime, int day, ArraySet<Integer> days) {
- append(TYPE_DOWNTIME, inDowntime + ",day=" + day + ",days=" + days);
+ public static void traceDowntime(int downtimeMode, int day, ArraySet<Integer> days) {
+ append(TYPE_DOWNTIME, zenModeToString(downtimeMode) + ",day=" + day + ",days=" + days);
}
public static void traceSetZenMode(int mode, String reason) {
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java
index 203d990..6d18531 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java
@@ -141,4 +141,11 @@ class CrossProfileIntentFilter extends IntentFilter {
return "CrossProfileIntentFilter{0x" + Integer.toHexString(System.identityHashCode(this))
+ " " + Integer.toString(mTargetUserId) + "}";
}
+
+ boolean equalsIgnoreFilter(CrossProfileIntentFilter other) {
+ return mTargetUserId == other.mTargetUserId
+ && mOwnerUserId == other.mOwnerUserId
+ && mOwnerPackage.equals(other.mOwnerPackage)
+ && mFlags == other.mFlags;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f9a85df..c75fb9a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11844,9 +11844,21 @@ public class PackageManagerService extends IPackageManager.Stub {
return;
}
synchronized (mPackages) {
- CrossProfileIntentFilter filter = new CrossProfileIntentFilter(intentFilter,
+ CrossProfileIntentFilter newFilter = new CrossProfileIntentFilter(intentFilter,
ownerPackage, UserHandle.getUserId(callingUid), targetUserId, flags);
- mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter(filter);
+ CrossProfileIntentResolver resolver =
+ mSettings.editCrossProfileIntentResolverLPw(sourceUserId);
+ ArrayList<CrossProfileIntentFilter> existing = resolver.findFilters(intentFilter);
+ // We have all those whose filter is equal. Now checking if the rest is equal as well.
+ if (existing != null) {
+ int size = existing.size();
+ for (int i = 0; i < size; i++) {
+ if (newFilter.equalsIgnoreFilter(existing.get(i))) {
+ return;
+ }
+ }
+ }
+ resolver.addFilter(newFilter);
scheduleWritePackageRestrictionsLocked(sourceUserId);
}
}
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index b1c918d..b2bcf75 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -27,11 +27,11 @@ import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Binder;
-import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PatternMatcher;
+import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -218,7 +218,7 @@ public class TrustAgentWrapper {
}
@Override
- public void onSetTrustAgentFeaturesEnabledCompleted(boolean result, IBinder token) {
+ public void onConfigureCompleted(boolean result, IBinder token) {
if (DEBUG) Slog.v(TAG, "onSetTrustAgentFeaturesEnabledCompleted(result=" + result);
mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_COMPLETED,
result ? 1 : 0, 0, token).sendToTarget();
@@ -318,23 +318,19 @@ public class TrustAgentWrapper {
DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- if ((dpm.getKeyguardDisabledFeatures(null)
+ if ((dpm.getKeyguardDisabledFeatures(null, mUserId)
& DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) {
- List<String> features = dpm.getTrustAgentFeaturesEnabled(null, mName);
+ List<PersistableBundle> config = dpm.getTrustAgentConfiguration(
+ null, mName, mUserId);
trustDisabled = true;
- if (DEBUG) Slog.v(TAG, "Detected trust agents disabled. Features = "
- + features);
- if (features != null && features.size() > 0) {
- Bundle bundle = new Bundle();
- bundle.putStringArrayList(TrustAgentService.KEY_FEATURES,
- (ArrayList<String>)features);
+ if (DEBUG) Slog.v(TAG, "Detected trust agents disabled. Config = " + config);
+ if (config != null && config.size() > 0) {
if (DEBUG) {
Slog.v(TAG, "TrustAgent " + mName.flattenToShortString()
- + " disabled until it acknowledges "+ features);
+ + " disabled until it acknowledges "+ config);
}
mSetTrustAgentFeaturesToken = new Binder();
- mTrustAgentService.setTrustAgentFeaturesEnabled(bundle,
- mSetTrustAgentFeaturesToken);
+ mTrustAgentService.onConfigure(config, mSetTrustAgentFeaturesToken);
}
}
final long maxTimeToLock = dpm.getMaximumTimeToLock(null);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 4437e12..fe5cb33 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -48,6 +48,7 @@ import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -228,10 +229,10 @@ public class TrustManagerService extends SystemService {
if (!enabledAgents.contains(name)) continue;
if (disableTrustAgents) {
- List<String> features =
- dpm.getTrustAgentFeaturesEnabled(null /* admin */, name);
+ List<PersistableBundle> config =
+ dpm.getTrustAgentConfiguration(null /* admin */, name, userInfo.id);
// Disable agent if no features are enabled.
- if (features == null || features.isEmpty()) continue;
+ if (config == null || config.isEmpty()) continue;
}
AgentInfo agentInfo = new AgentInfo();
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index bfc7659..eeb007c 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -691,8 +691,10 @@ public class AppTransition implements Dump {
throw new RuntimeException("Invalid thumbnail transition state");
}
- return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight,
- THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailFastOutSlowInInterpolator);
+ int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION,
+ THUMBNAIL_APP_TRANSITION_DURATION);
+ return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
+ mThumbnailFastOutSlowInInterpolator);
}
/**
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 69c9144..bf96ea5 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -58,7 +58,9 @@ public class AppWindowAnimator {
// the state changes.
boolean allDrawn;
- // Special surface for thumbnail animation.
+ // Special surface for thumbnail animation. If deferThumbnailDestruction is enabled, then we
+ // will make sure that the thumbnail is destroyed after the other surface is completed. This
+ // requires that the duration of the two animations are the same.
SurfaceControl thumbnail;
int thumbnailTransactionSeq;
int thumbnailX;
@@ -68,13 +70,12 @@ public class AppWindowAnimator {
Animation thumbnailAnimation;
final Transformation thumbnailTransformation = new Transformation();
// This flag indicates that the destruction of the thumbnail surface is synchronized with
- // another animation, so do not pre-emptively destroy the thumbnail surface when the animation
- // completes
+ // another animation, so defer the destruction of this thumbnail surface for a single frame
+ // after the secondary animation completes.
boolean deferThumbnailDestruction;
- // This is the thumbnail surface that has been bestowed upon this animator, and when the
- // surface for this animator's animation is complete, we will destroy the thumbnail surface
- // as well. Do not animate or do anything with this surface.
- SurfaceControl deferredThumbnail;
+ // This flag is set if the animator has deferThumbnailDestruction set and has reached the final
+ // frame of animation. It will extend the animation by one frame and then clean up afterwards.
+ boolean deferFinalFrameCleanup;
/** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
@@ -134,9 +135,7 @@ public class AppWindowAnimator {
animation = null;
animating = true;
}
- if (!deferThumbnailDestruction) {
- clearThumbnail();
- }
+ clearThumbnail();
if (mAppToken.deferClearAllDrawn) {
mAppToken.allDrawn = false;
mAppToken.deferClearAllDrawn = false;
@@ -148,13 +147,7 @@ public class AppWindowAnimator {
thumbnail.destroy();
thumbnail = null;
}
- }
-
- public void clearDeferredThumbnail() {
- if (deferredThumbnail != null) {
- deferredThumbnail.destroy();
- deferredThumbnail = null;
- }
+ deferThumbnailDestruction = false;
}
void updateLayers() {
@@ -223,19 +216,26 @@ public class AppWindowAnimator {
return false;
}
transformation.clear();
- final boolean more = animation.getTransformation(currentTime, transformation);
- if (false && WindowManagerService.DEBUG_ANIM) Slog.v(
- TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
- if (!more) {
- animation = null;
- if (!deferThumbnailDestruction) {
+ boolean hasMoreFrames = animation.getTransformation(currentTime, transformation);
+ if (!hasMoreFrames) {
+ if (deferThumbnailDestruction && !deferFinalFrameCleanup) {
+ // We are deferring the thumbnail destruction, so extend the animation for one more
+ // (dummy) frame before we clean up
+ deferFinalFrameCleanup = true;
+ hasMoreFrames = true;
+ } else {
+ if (false && WindowManagerService.DEBUG_ANIM) Slog.v(
+ TAG, "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames +
+ ", xform=" + transformation);
+ deferFinalFrameCleanup = false;
+ animation = null;
clearThumbnail();
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
}
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
}
- hasTransformation = more;
- return more;
+ hasTransformation = hasMoreFrames;
+ return hasMoreFrames;
}
// This must be called while inside a transaction.
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 61ea1e8..c002ddf 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -91,6 +91,9 @@ public class WindowAnimator {
boolean mKeyguardGoingAwayToNotificationShade;
boolean mKeyguardGoingAwayDisableWindowAnimations;
+ /** Use one animation for all entering activities after keyguard is dismissed. */
+ Animation mPostKeyguardExitAnimation;
+
// forceHiding states.
static final int KEYGUARD_NOT_SHOWN = 0;
static final int KEYGUARD_ANIMATING_IN = 1;
@@ -220,9 +223,6 @@ public class WindowAnimator {
++mAnimTransactionSequence;
final WindowList windows = mService.getWindowListLocked(displayId);
- ArrayList<WindowStateAnimator> unForceHiding = null;
- boolean wallpaperInUnForceHiding = false;
- WindowState wallpaper = null;
if (mKeyguardGoingAway) {
for (int i = windows.size() - 1; i >= 0; i--) {
@@ -261,6 +261,9 @@ public class WindowAnimator {
final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
null : winShowWhenLocked.mAppToken;
+ boolean wallpaperInUnForceHiding = false;
+ ArrayList<WindowStateAnimator> unForceHiding = null;
+ WindowState wallpaper = null;
for (int i = windows.size() - 1; i >= 0; i--) {
WindowState win = windows.get(i);
WindowStateAnimator winAnimator = win.mWinAnimator;
@@ -269,6 +272,7 @@ public class WindowAnimator {
if (winAnimator.mSurfaceControl != null) {
final boolean wasAnimating = winAnimator.mWasAnimating;
final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
+ mAnimating |= nowAnimating;
if (WindowManagerService.DEBUG_WALLPAPER) {
Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
@@ -327,40 +331,53 @@ public class WindowAnimator {
} else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
final boolean hideWhenLocked = !((win.mIsImWindow && showImeOverKeyguard) ||
(appShowWhenLocked != null && appShowWhenLocked == win.mAppToken));
- final boolean changed;
if (((mForceHiding == KEYGUARD_ANIMATING_IN)
&& (!winAnimator.isAnimating() || hideWhenLocked))
|| ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
- changed = win.hideLw(false, false);
- if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY)
- && changed) Slog.v(TAG, "Now policy hidden: " + win);
+ if (!win.hideLw(false, false)) {
+ // Was already hidden
+ continue;
+ }
+ if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+ "Now policy hidden: " + win);
} else {
- changed = win.showLw(false, false);
- if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY)
- && changed) Slog.v(TAG, "Now policy shown: " + win);
- if (changed) {
- if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
- && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
- if (unForceHiding == null) {
- unForceHiding = new ArrayList<WindowStateAnimator>();
- }
- unForceHiding.add(winAnimator);
- if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
- wallpaperInUnForceHiding = true;
- }
+ if (!win.showLw(false, false)) {
+ // Was already showing.
+ continue;
+ }
+ final boolean visibleNow = win.isVisibleNow();
+ if (!visibleNow) {
+ // Couldn't really show, must showLw() again when win becomes visible.
+ win.hideLw(false, false);
+ continue;
+ }
+ if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+ "Now policy shown: " + win);
+ if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
+ if (unForceHiding == null) {
+ unForceHiding = new ArrayList<>();
}
- final WindowState currentFocus = mService.mCurrentFocus;
- if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
- // We are showing on to of the current
- // focus, so re-evaluate focus to make
- // sure it is correct.
- if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG,
- "updateWindowsLocked: setting mFocusMayChange true");
- mService.mFocusMayChange = true;
+ unForceHiding.add(winAnimator);
+ if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
+ wallpaperInUnForceHiding = true;
}
+ } else if (mPostKeyguardExitAnimation != null) {
+ // We're already in the middle of an animation. Use the existing
+ // animation to bring in this window.
+ winAnimator.setAnimation(mPostKeyguardExitAnimation);
+ winAnimator.keyguardGoingAwayAnimation = true;
+ }
+ final WindowState currentFocus = mService.mCurrentFocus;
+ if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
+ // We are showing on top of the current
+ // focus, so re-evaluate focus to make
+ // sure it is correct.
+ if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG,
+ "updateWindowsLocked: setting mFocusMayChange true");
+ mService.mFocusMayChange = true;
}
}
- if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) {
+ if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
@@ -403,29 +420,20 @@ public class WindowAnimator {
// If we have windows that are being show due to them no longer
// being force-hidden, apply the appropriate animation to them.
if (unForceHiding != null) {
- boolean startKeyguardExit = true;
- for (int i=unForceHiding.size()-1; i>=0; i--) {
- Animation a = null;
- if (!mKeyguardGoingAwayDisableWindowAnimations) {
- a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding,
- mKeyguardGoingAwayToNotificationShade);
- if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: created anim=" + a
- + " for win=" + unForceHiding.get(i));
- } else {
- if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: skipping anim for win="
- + unForceHiding.get(i));
- }
- if (a != null) {
+ // This only happens the first time that we detect the keyguard is animating out.
+ if (mKeyguardGoingAwayDisableWindowAnimations) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: skipping anim for windows");
+ } else {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: created anim for windows="
+ + unForceHiding);
+ mPostKeyguardExitAnimation = mPolicy.createForceHideEnterAnimation(
+ wallpaperInUnForceHiding, mKeyguardGoingAwayToNotificationShade);
+ }
+ if (mPostKeyguardExitAnimation != null) {
+ for (int i=unForceHiding.size()-1; i>=0; i--) {
final WindowStateAnimator winAnimator = unForceHiding.get(i);
- winAnimator.setAnimation(a);
+ winAnimator.setAnimation(mPostKeyguardExitAnimation);
winAnimator.keyguardGoingAwayAnimation = true;
- if (startKeyguardExit && mKeyguardGoingAway) {
- // Do one time only.
- mPolicy.startKeyguardExitAnimation(mCurrentTime + a.getStartOffset(),
- a.getDuration());
- mKeyguardGoingAway = false;
- startKeyguardExit = false;
- }
}
}
@@ -436,11 +444,23 @@ public class WindowAnimator {
Animation a = mPolicy.createForceHideWallpaperExitAnimation(
mKeyguardGoingAwayToNotificationShade);
if (a != null) {
- WindowStateAnimator animator = wallpaper.mWinAnimator;
- animator.setAnimation(a);
+ wallpaper.mWinAnimator.setAnimation(a);
}
}
}
+
+ if (mPostKeyguardExitAnimation != null) {
+ // We're in the midst of a keyguard exit animation.
+ if (mKeyguardGoingAway) {
+ mPolicy.startKeyguardExitAnimation(mCurrentTime +
+ mPostKeyguardExitAnimation.getStartOffset(),
+ mPostKeyguardExitAnimation.getDuration());
+ mKeyguardGoingAway = false;
+ } else if (mPostKeyguardExitAnimation.hasEnded()) {
+ // Done with the animation, reset.
+ mPostKeyguardExitAnimation = null;
+ }
+ }
}
private void updateWallpaperLocked(int displayId) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b4e2778..968b35c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -9244,12 +9244,6 @@ public class WindowManagerService extends IWindowManager.Stub
topClosingLayer);
openingAppAnimator.deferThumbnailDestruction =
!mAppTransition.isNextThumbnailTransitionScaleUp();
- if (openingAppAnimator.deferThumbnailDestruction) {
- if (closingAppAnimator != null &&
- closingAppAnimator.animation != null) {
- closingAppAnimator.deferredThumbnail = surfaceControl;
- }
- }
} else {
anim = mAppTransition.createThumbnailScaleAnimationLocked(
displayInfo.appWidth, displayInfo.appHeight, transit);
@@ -9783,7 +9777,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (!w.isDrawnLw()) {
Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
+ " pv=" + w.mPolicyVisibility
- + " mDrawState=" + winAnimator.mDrawState
+ + " mDrawState=" + winAnimator.drawStateToString()
+ " ah=" + w.mAttachedHidden
+ " th=" + atoken.hiddenRequested
+ " a=" + winAnimator.mAnimating);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index fc3f2c2..819ca50 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -167,14 +167,14 @@ class WindowStateAnimator {
private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
- static String drawStateToString(int state) {
- switch (state) {
+ String drawStateToString() {
+ switch (mDrawState) {
case NO_SURFACE: return "NO_SURFACE";
case DRAW_PENDING: return "DRAW_PENDING";
case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING";
case READY_TO_SHOW: return "READY_TO_SHOW";
case HAS_DRAWN: return "HAS_DRAWN";
- default: return Integer.toString(state);
+ default: return Integer.toString(mDrawState);
}
}
int mDrawState;
@@ -486,20 +486,23 @@ class WindowStateAnimator {
}
boolean finishDrawingLocked() {
- if (DEBUG_STARTING_WINDOW &&
- mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
+ final boolean startingWindow =
+ mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+ if (DEBUG_STARTING_WINDOW && startingWindow) {
Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState="
- + drawStateToString(mDrawState));
+ + drawStateToString());
}
if (mDrawState == DRAW_PENDING) {
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in "
+ mSurfaceControl);
- if (DEBUG_STARTING_WINDOW &&
- mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
+ if (DEBUG_STARTING_WINDOW && startingWindow) {
Slog.v(TAG, "Draw state now committed in " + mWin);
}
mDrawState = COMMIT_DRAW_PENDING;
+ if (startingWindow) {
+ mService.notifyActivityDrawnForKeyguard();
+ }
return true;
}
return false;
@@ -510,18 +513,17 @@ class WindowStateAnimator {
if (DEBUG_STARTING_WINDOW &&
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
- + drawStateToString(mDrawState));
+ + drawStateToString());
}
- if (mDrawState != COMMIT_DRAW_PENDING) {
+ if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
return false;
}
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) {
Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceControl);
}
mDrawState = READY_TO_SHOW;
- final boolean starting = mWin.mAttrs.type == TYPE_APPLICATION_STARTING;
final AppWindowToken atoken = mWin.mAppToken;
- if (atoken == null || atoken.allDrawn || starting) {
+ if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
performShowLocked();
}
return true;
@@ -976,11 +978,6 @@ class WindowStateAnimator {
mWin.mHasSurface = false;
mDrawState = NO_SURFACE;
}
-
- // Destroy any deferred thumbnail surfaces
- if (mAppAnimator != null) {
- mAppAnimator.clearDeferredThumbnail();
- }
}
void destroyDeferredSurfaceLocked() {
@@ -1868,7 +1865,7 @@ class WindowStateAnimator {
if (dumpAll) {
pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);
pw.print(prefix); pw.print("mDrawState=");
- pw.print(drawStateToString(mDrawState));
+ pw.print(drawStateToString());
pw.print(" mLastHidden="); pw.println(mLastHidden);
}
pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
index 6958087..8183321 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -1195,6 +1195,7 @@ static jobject translate_gps_measurement(JNIEnv* env, GpsMeasurement* measuremen
usedInFixSetterMethod,
(flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
+ env->DeleteLocalRef(gpsMeasurementClass);
return gpsMeasurementObject;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 308fcd8..2c6a222 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -60,6 +60,7 @@ import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.IPowerManager;
+import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.Process;
import android.os.RecoverySystem;
@@ -96,6 +97,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.org.conscrypt.TrustedCertificateStore;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
import org.xmlpull.v1.XmlPullParser;
@@ -322,7 +324,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
= "permitted-accessiblity-services";
private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
private static final String TAG_MANAGE_TRUST_AGENT_FEATURES = "manage-trust-agent-features";
- private static final String TAG_TRUST_AGENT_FEATURE = "feature";
+ private static final String TAG_TRUST_AGENT_COMPONENT_OPTIONS = "trust-agent-component-options";
private static final String TAG_TRUST_AGENT_COMPONENT = "component";
private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date";
private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout";
@@ -389,6 +391,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
+
int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
boolean encryptionRequested = false;
@@ -397,6 +400,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
boolean requireAutoTime = false; // Can only be set by a device owner.
+ static class TrustAgentInfo {
+ public PersistableBundle options;
+ TrustAgentInfo(PersistableBundle bundle) {
+ options = bundle;
+ }
+ }
+
Set<String> accountTypesWithManagementDisabled = new HashSet<String>();
// The list of permitted accessibility services package namesas set by a profile
@@ -413,7 +423,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean specifiesGlobalProxy = false;
String globalProxySpec = null;
String globalProxyExclusionList = null;
- HashMap<String, List<String>> trustAgentFeatures = new HashMap<String, List<String>>();
+
+ HashMap<String, TrustAgentInfo> trustAgentInfos = new HashMap<String, TrustAgentInfo>();
List<String> crossProfileWidgetProviders;
@@ -551,16 +562,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
out.endTag(null, TAG_DISABLE_ACCOUNT_MANAGEMENT);
}
- if (!trustAgentFeatures.isEmpty()) {
- Set<Entry<String, List<String>>> set = trustAgentFeatures.entrySet();
+ if (!trustAgentInfos.isEmpty()) {
+ Set<Entry<String, TrustAgentInfo>> set = trustAgentInfos.entrySet();
out.startTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
- for (Entry<String, List<String>> component : set) {
+ for (Entry<String, TrustAgentInfo> entry : set) {
+ TrustAgentInfo trustAgentInfo = entry.getValue();
out.startTag(null, TAG_TRUST_AGENT_COMPONENT);
- out.attribute(null, ATTR_VALUE, component.getKey());
- for (String feature : component.getValue()) {
- out.startTag(null, TAG_TRUST_AGENT_FEATURE);
- out.attribute(null, ATTR_VALUE, feature);
- out.endTag(null, TAG_TRUST_AGENT_FEATURE);
+ out.attribute(null, ATTR_VALUE, entry.getKey());
+ if (trustAgentInfo.options != null) {
+ out.startTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
+ try {
+ trustAgentInfo.options.saveToXml(out);
+ } catch (XmlPullParserException e) {
+ Log.e(LOG_TAG, "Failed to save TrustAgent options", e);
+ }
+ out.endTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
}
out.endTag(null, TAG_TRUST_AGENT_COMPONENT);
}
@@ -679,7 +695,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) {
accountTypesWithManagementDisabled = readDisableAccountInfo(parser, tag);
} else if (TAG_MANAGE_TRUST_AGENT_FEATURES.equals(tag)) {
- trustAgentFeatures = getAllTrustAgentFeatures(parser, tag);
+ trustAgentInfos = getAllTrustAgentInfos(parser, tag);
} else if (TAG_CROSS_PROFILE_WIDGET_PROVIDERS.equals(tag)) {
crossProfileWidgetProviders = getCrossProfileWidgetProviders(parser, tag);
} else if (TAG_PERMITTED_ACCESSIBILITY_SERVICES.equals(tag)) {
@@ -738,11 +754,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return result;
}
- private HashMap<String, List<String>> getAllTrustAgentFeatures(XmlPullParser parser,
- String tag) throws XmlPullParserException, IOException {
+ private HashMap<String, TrustAgentInfo> getAllTrustAgentInfos(
+ XmlPullParser parser, String tag) throws XmlPullParserException, IOException {
int outerDepthDAM = parser.getDepth();
int typeDAM;
- HashMap<String, List<String>> result = new HashMap<String, List<String>>();
+ HashMap<String, TrustAgentInfo> result = new HashMap<String, TrustAgentInfo>();
while ((typeDAM=parser.next()) != END_DOCUMENT
&& (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
if (typeDAM == END_TAG || typeDAM == TEXT) {
@@ -751,7 +767,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
String tagDAM = parser.getName();
if (TAG_TRUST_AGENT_COMPONENT.equals(tagDAM)) {
final String component = parser.getAttributeValue(null, ATTR_VALUE);
- result.put(component, getTrustAgentFeatures(parser, tag));
+ final TrustAgentInfo trustAgentInfo = getTrustAgentInfo(parser, tag);
+ result.put(component, trustAgentInfo);
} else {
Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
}
@@ -759,20 +776,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return result;
}
- private List<String> getTrustAgentFeatures(XmlPullParser parser, String tag)
+ private TrustAgentInfo getTrustAgentInfo(XmlPullParser parser, String tag)
throws XmlPullParserException, IOException {
int outerDepthDAM = parser.getDepth();
int typeDAM;
- ArrayList<String> result = new ArrayList<String>();
+ TrustAgentInfo result = new TrustAgentInfo(null);
while ((typeDAM=parser.next()) != END_DOCUMENT
&& (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
if (typeDAM == END_TAG || typeDAM == TEXT) {
continue;
}
String tagDAM = parser.getName();
- if (TAG_TRUST_AGENT_FEATURE.equals(tagDAM)) {
- final String feature = parser.getAttributeValue(null, ATTR_VALUE);
- result.add(feature);
+ if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.restoreFromXml(parser);
+ result.options = bundle;
} else {
Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
}
@@ -1174,7 +1192,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int userHandle) {
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo ui : profiles) {
- int id = ui.getUserHandle().getIdentifier();
+ int id = ui.id;
sendAdminCommandLocked(action, reqPolicy, id);
}
}
@@ -1591,7 +1609,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo ui : profiles) {
- int profileUserHandle = ui.getUserHandle().getIdentifier();
+ int profileUserHandle = ui.id;
final DevicePolicyData policy = getUserData(profileUserHandle);
final int count = policy.mAdminList.size();
if (count > 0) {
@@ -1878,7 +1896,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -1925,7 +1943,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -1972,7 +1990,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2033,7 +2051,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2131,7 +2149,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2188,7 +2206,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2232,7 +2250,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2279,7 +2297,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2326,7 +2344,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2373,7 +2391,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2420,7 +2438,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2526,7 +2544,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int count = 0;
ActiveAdmin strictestAdmin = null;
for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
for (ActiveAdmin admin : policy.mAdminList) {
if (admin.maximumFailedPasswordsForWipe ==
ActiveAdmin.DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
@@ -2738,7 +2756,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Return strictest policy for this user and profiles that are visible from this user.
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -3055,7 +3073,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private void updatePasswordExpirationsLocked(int userHandle) {
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
- int profileId = userInfo.getUserHandle().getIdentifier();
+ int profileId = userInfo.id;
DevicePolicyData policy = getUserData(profileId);
final int N = policy.mAdminList.size();
if (N > 0) {
@@ -4106,13 +4124,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
- List<String>features, int userHandle) {
+ public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent,
+ PersistableBundle args, int userHandle) {
if (!mHasFeature) {
return;
}
enforceCrossUserPermission(userHandle);
- enforceNotManagedProfile(userHandle, "manage trust agent features");
+ enforceNotManagedProfile(userHandle, "set trust agent configuration");
synchronized (this) {
if (admin == null) {
throw new NullPointerException("admin is null");
@@ -4122,57 +4140,68 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
- ap.trustAgentFeatures.put(agent.flattenToString(), features);
+ ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
saveSettingsLocked(userHandle);
syncDeviceCapabilitiesLocked(getUserData(userHandle));
}
}
- public List<String> getTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
- int userHandle) {
+ public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
+ ComponentName agent, int userHandle) {
if (!mHasFeature) {
return null;
}
enforceCrossUserPermission(userHandle);
+ if (agent == null) {
+ throw new NullPointerException("agent is null");
+ }
+
synchronized (this) {
- if (agent == null) {
- throw new NullPointerException("agent is null");
- }
final String componentName = agent.flattenToString();
if (admin != null) {
final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle);
- return (ap != null) ? ap.trustAgentFeatures.get(componentName) : null;
+ if (ap == null) return null;
+ TrustAgentInfo trustAgentInfo = ap.trustAgentInfos.get(componentName);
+ if (trustAgentInfo == null || trustAgentInfo.options == null) return null;
+ List<PersistableBundle> result = new ArrayList<PersistableBundle>();
+ result.add(trustAgentInfo.options);
+ return result;
}
// Return strictest policy for this user and profiles that are visible from this user.
- List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
- List<String> result = null;
+ final List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ List<PersistableBundle> result = null;
+
+ // Search through all admins that use KEYGUARD_DISABLE_TRUST_AGENTS and keep track
+ // of the options. If any admin doesn't have options, discard options for the rest
+ // and return null.
+ boolean allAdminsHaveOptions = true;
for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ DevicePolicyData policy = getUserData(userInfo.id);
final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin ap = policy.mAdminList.get(i);
- // Compute the intersection of all features for active admins that disable
- // trust agents:
- if ((ap.disabledKeyguardFeatures
- & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) {
- final List<String> features = ap.trustAgentFeatures.get(componentName);
- if (result == null) {
- if (features == null || features.size() == 0) {
- result = new ArrayList<String>();
- Slog.w(LOG_TAG, "admin " + ap.info.getPackageName()
- + " has null trust agent feature set; all will be disabled");
- } else {
- result = new ArrayList<String>(features.size());
- result.addAll(features);
+ for (int i=0; i < N; i++) {
+ final ActiveAdmin active = policy.mAdminList.get(i);
+ final boolean disablesTrust = (active.disabledKeyguardFeatures
+ & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
+ final TrustAgentInfo info = active.trustAgentInfos.get(componentName);
+ if (info != null && info.options != null && !info.options.isEmpty()) {
+ if (disablesTrust) {
+ if (result == null) {
+ result = new ArrayList<PersistableBundle>();
}
+ result.add(info.options);
} else {
- result.retainAll(features);
+ Log.w(LOG_TAG, "Ignoring admin " + active.info
+ + " because it has trust options but doesn't declare "
+ + "KEYGUARD_DISABLE_TRUST_AGENTS");
}
+ } else if (disablesTrust) {
+ allAdminsHaveOptions = false;
+ break;
}
}
}
- return result;
+ return allAdminsHaveOptions ? result : null;
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 11da380..098b3ef 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -119,6 +119,7 @@ class UsageStatsDatabase {
if (!files.valueAt(start).getBaseFile().getName().endsWith("-c")) {
break;
}
+ start++;
}
if (start == fileCount - 1) {
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 003d5cd..6480a8a 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -207,6 +207,13 @@ public abstract class Conference {
}
/**
+ * @return The {@link DisconnectCause} for this connection.
+ */
+ public final DisconnectCause getDisconnectCause() {
+ return mDisconnectCause;
+ }
+
+ /**
* Sets the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
*
* @param capabilities A bitmask of the {@code PhoneCapabilities} of the conference call.
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 9bdbba8..34d0660 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -974,6 +974,15 @@ public abstract class Connection {
public void onDisconnect() {}
/**
+ * Notifies this Connection of a request to disconnect a participant of the conference managed
+ * by the connection.
+ *
+ * @param endpoint the {@link Uri} of the participant to disconnect.
+ * @hide
+ */
+ public void onDisconnectConferenceParticipant(Uri endpoint) {}
+
+ /**
* Notifies this Connection of a request to separate from its parent conference.
*/
public void onSeparate() {}
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 206046d..73bcd0c 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -58,6 +58,11 @@ public final class DisconnectCause implements Parcelable {
public static final int RESTRICTED = 8;
/** Disconnected for reason not described by other disconnect codes. */
public static final int OTHER = 9;
+ /**
+ * Disconnected because the connection manager did not support the call. The call will be tried
+ * again without a connection manager. See {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}.
+ */
+ public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10;
private int mDisconnectCode;
private CharSequence mDisconnectLabel;
@@ -220,7 +225,10 @@ public final class DisconnectCause implements Parcelable {
@Override
public String toString() {
String code = "";
- switch (getCode()) {
+ switch (mDisconnectCode) {
+ case UNKNOWN:
+ code = "UNKNOWN";
+ break;
case ERROR:
code = "ERROR";
break;
@@ -230,6 +238,9 @@ public final class DisconnectCause implements Parcelable {
case REMOTE:
code = "REMOTE";
break;
+ case CANCELED:
+ code = "CANCELED";
+ break;
case MISSED:
code = "MISSED";
break;
@@ -245,9 +256,12 @@ public final class DisconnectCause implements Parcelable {
case OTHER:
code = "OTHER";
break;
- case UNKNOWN:
+ case CONNECTION_MANAGER_NOT_SUPPORTED:
+ code = "CONNECTION_MANAGER_NOT_SUPPORTED";
+ break;
default:
- code = "UNKNOWN";
+ code = "invalid code: " + mDisconnectCode;
+ break;
}
String label = mDisconnectLabel == null ? "" : mDisconnectLabel.toString();
String description = mDisconnectDescription == null
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 4eac5ac..ecf6005 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -17,6 +17,7 @@ package android.telecom;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
+import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -337,8 +338,6 @@ public class TelecomManager {
* @param uriScheme The URI scheme.
* @return The {@link PhoneAccountHandle} corresponding to the user-chosen default for outgoing
* phone calls for a specified URI scheme.
- *
- * @hide
*/
public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
try {
@@ -458,8 +457,6 @@ public class TelecomManager {
*
* @param uriScheme The URI scheme.
* @return A list of {@code PhoneAccountHandle} objects supporting the URI scheme.
- *
- * @hide
*/
public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
try {
@@ -926,7 +923,6 @@ public class TelecomManager {
* @param accountHandle The handle for the account the MMI code should apply to.
* @param dialString The digits to dial.
* @return True if the digits were processed as an MMI code, false otherwise.
- *
*/
public boolean handleMmi(PhoneAccountHandle accountHandle, String dialString) {
ITelecomService service = getTelecomService();
@@ -941,6 +937,24 @@ public class TelecomManager {
}
/**
+ * @param accountHandle The handle for the account to derive an adn query URI for or
+ * {@code null} to return a URI which will use the default account.
+ * @return The URI (with the content:// scheme) specific to the specified {@link PhoneAccount}
+ * for the the content retrieve.
+ */
+ public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle) {
+ ITelecomService service = getTelecomService();
+ if (service != null && accountHandle != null) {
+ try {
+ return service.getAdnUriForPhoneAccount(accountHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecomService#getAdnUriForPhoneAccount", e);
+ }
+ }
+ return Uri.parse("content://icc/adn");
+ }
+
+ /**
* Removes the missed-call notification if one is present.
* <p>
* Requires that the method-caller be set as the system dialer app.
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index fd47213..cbd9d69 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -18,6 +18,7 @@ package com.android.internal.telecom;
import android.content.ComponentName;
import android.telecom.PhoneAccountHandle;
+import android.net.Uri;
import android.os.Bundle;
import android.telecom.PhoneAccount;
@@ -174,6 +175,11 @@ interface ITelecomService {
boolean handlePinMmiForPhoneAccount(in PhoneAccountHandle accountHandle, String dialString);
/**
+ * @see TelecomServiceImpl#getAdnUriForPhoneAccount
+ */
+ Uri getAdnUriForPhoneAccount(in PhoneAccountHandle accountHandle);
+
+ /**
* @see TelecomServiceImpl#isTtySupported
*/
boolean isTtySupported();
diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java
index 4a3d67e..8ab69cc 100644
--- a/telephony/java/android/telephony/SubInfoRecord.java
+++ b/telephony/java/android/telephony/SubInfoRecord.java
@@ -29,98 +29,138 @@ public class SubInfoRecord implements Parcelable {
* Subscription Identifier, this is a device unique number
* and not an index into an array
*/
- public int subId;
- /** The GID for a SIM that maybe associated with this subscription, empty if unknown */
- public String iccId;
+ private int mId;
+
+ /**
+ * The GID for a SIM that maybe associated with this subscription, empty if unknown
+ */
+ private String mIccId;
+
/**
- * The slot identifier for that currently contains the subscription
+ * The index of the slot that currently contains the subscription
* and not necessarily unique and maybe INVALID_SLOT_ID if unknown
*/
- public int slotId;
+ private int mSimSlotIndex;
+
/**
- * The string displayed to the user that identifies this subscription
+ * The name displayed to the user that identifies this subscription
*/
- public String displayName;
+ private CharSequence mDisplayName;
+
/**
* The source of the name, NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE,
* NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
*/
- public int nameSource;
+ private int mNameSource;
+
/**
* The color to be used for when displaying to the user
*/
- public int color;
+ private int mColor;
+
/**
* A number presented to the user identify this subscription
*/
- public String number;
- /**
- * How to display the phone number, DISPLAY_NUMBER_NONE, DISPLAY_NUMBER_FIRST,
- * DISPLAY_NUMBER_LAST
- */
- public int displayNumberFormat;
+ private String mNumber;
+
/**
* Data roaming state, DATA_RAOMING_ENABLE, DATA_RAOMING_DISABLE
*/
- public int dataRoaming;
+ private int mDataRoaming;
+
/**
* SIM Icon resource identifiers. FIXME: Check with MTK what it really is
*/
- public int[] simIconRes;
+ private int[] mSimIconRes;
+
/**
* Mobile Country Code
*/
- public int mcc;
+ private int mMcc;
+
/**
* Mobile Network Code
*/
- public int mnc;
+ private int mMnc;
+ /**
+ * @hide
public SubInfoRecord() {
- this.subId = SubscriptionManager.INVALID_SUB_ID;
- this.iccId = "";
- this.slotId = SubscriptionManager.INVALID_SLOT_ID;
- this.displayName = "";
- this.nameSource = 0;
- this.color = 0;
- this.number = "";
- this.displayNumberFormat = 0;
- this.dataRoaming = 0;
- this.simIconRes = new int[2];
- this.mcc = 0;
- this.mnc = 0;
+ this.mId = SubscriptionManager.INVALID_SUB_ID;
+ this.mIccId = "";
+ this.mSimSlotIndex = SubscriptionManager.INVALID_SLOT_ID;
+ this.mDisplayName = "";
+ this.mNameSource = 0;
+ this.mColor = 0;
+ this.mNumber = "";
+ this.mDataRoaming = 0;
+ this.mSimIconRes = new int[2];
+ this.mMcc = 0;
+ this.mMnc = 0;
}
+ */
- public SubInfoRecord(int subId, String iccId, int slotId, String displayName, int nameSource,
- int color, String number, int displayFormat, int roaming, int[] iconRes,
- int mcc, int mnc) {
- this.subId = subId;
- this.iccId = iccId;
- this.slotId = slotId;
- this.displayName = displayName;
- this.nameSource = nameSource;
- this.color = color;
- this.number = number;
- this.displayNumberFormat = displayFormat;
- this.dataRoaming = roaming;
- this.simIconRes = iconRes;
- this.mcc = mcc;
- this.mnc = mnc;
+ /**
+ * @hide
+ */
+ public SubInfoRecord(int id, String iccId, int simSlotIndex, CharSequence displayName,
+ int nameSource, int color, String number, int roaming, int[] iconRes, int mcc,
+ int mnc) {
+ this.mId = id;
+ this.mIccId = iccId;
+ this.mSimSlotIndex = simSlotIndex;
+ this.mDisplayName = displayName;
+ this.mNameSource = nameSource;
+ this.mColor = color;
+ this.mNumber = number;
+ this.mDataRoaming = roaming;
+ this.mSimIconRes = iconRes;
+ this.mMcc = mcc;
+ this.mMnc = mnc;
}
/**
- * Returns the string displayed to the user that identifies this subscription
+ * Returns the subscription ID.
*/
- public String getLabel() {
- return this.displayName;
+ public int getSubscriptionId() {
+ return this.mId;
}
/**
- * Return the icon used to identify this SIM.
- * TODO: return the correct drawable.
+ * Returns the ICC ID.
*/
- public BitmapDrawable getIconDrawable() {
- return new BitmapDrawable();
+ public String getIccId() {
+ return this.mIccId;
+ }
+
+ /**
+ * Returns the slot index of this Subscription's SIM card.
+ */
+ public int getSimSlotIndex() {
+ return this.mSimSlotIndex;
+ }
+
+ /**
+ * Returns the name displayed to the user that identifies this subscription
+ */
+ public CharSequence getDisplayName() {
+ return this.mDisplayName;
+ }
+
+ /**
+ * Sets the name displayed to the user that identifies this subscription
+ * @hide
+ */
+ public void setDisplayName(CharSequence name) {
+ this.mDisplayName = name;
+ }
+
+ /**
+ * Return the source of the name, eg NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE,
+ * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
+ */
+ public int getNameSource() {
+ return this.mNameSource;
}
/**
@@ -130,28 +170,70 @@ public class SubInfoRecord implements Parcelable {
public int getColor() {
// Note: This color is currently an index into a list of drawables, but this is soon to
// change.
- return this.color;
+ return this.mColor;
+ }
+
+ /**
+ * Sets the color displayed to the user that identifies this subscription
+ * @hide
+ */
+ public void setColor(int color) {
+ this.mColor = color;
+ }
+
+ /**
+ * Returns the number of this subscription.
+ */
+ public String getNumber() {
+ return mNumber;
+ }
+
+ /**
+ * Return the data roaming value.
+ */
+ public int getDataRoaming() {
+ return this.mDataRoaming;
+ }
+
+ /**
+ * Return the icon used to identify this subscription.
+ */
+ public BitmapDrawable getIcon() {
+ return new BitmapDrawable();
+ }
+
+ /**
+ * Returns the MCC.
+ */
+ public int getMcc() {
+ return this.mMcc;
+ }
+
+ /**
+ * Returns the MNC.
+ */
+ public int getMnc() {
+ return this.mMnc;
}
public static final Parcelable.Creator<SubInfoRecord> CREATOR = new Parcelable.Creator<SubInfoRecord>() {
@Override
public SubInfoRecord createFromParcel(Parcel source) {
- int subId = source.readInt();
+ int id = source.readInt();
String iccId = source.readString();
- int slotId = source.readInt();
- String displayName = source.readString();
+ int simSlotIndex = source.readInt();
+ CharSequence displayName = source.readCharSequence();
int nameSource = source.readInt();
int color = source.readInt();
String number = source.readString();
- int displayNumberFormat = source.readInt();
int dataRoaming = source.readInt();
int[] iconRes = new int[2];
source.readIntArray(iconRes);
int mcc = source.readInt();
int mnc = source.readInt();
- return new SubInfoRecord(subId, iccId, slotId, displayName, nameSource, color, number,
- displayNumberFormat, dataRoaming, iconRes, mcc, mnc);
+ return new SubInfoRecord(id, iccId, simSlotIndex, displayName, nameSource, color, number,
+ dataRoaming, iconRes, mcc, mnc);
}
@Override
@@ -162,18 +244,17 @@ public class SubInfoRecord implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(subId);
- dest.writeString(iccId);
- dest.writeInt(slotId);
- dest.writeString(displayName);
- dest.writeInt(nameSource);
- dest.writeInt(color);
- dest.writeString(number);
- dest.writeInt(displayNumberFormat);
- dest.writeInt(dataRoaming);
- dest.writeIntArray(simIconRes);
- dest.writeInt(mcc);
- dest.writeInt(mnc);
+ dest.writeInt(mId);
+ dest.writeString(mIccId);
+ dest.writeInt(mSimSlotIndex);
+ dest.writeCharSequence(mDisplayName);
+ dest.writeInt(mNameSource);
+ dest.writeInt(mColor);
+ dest.writeString(mNumber);
+ dest.writeInt(mDataRoaming);
+ dest.writeIntArray(mSimIconRes);
+ dest.writeInt(mMcc);
+ dest.writeInt(mMnc);
}
@Override
@@ -183,10 +264,9 @@ public class SubInfoRecord implements Parcelable {
@Override
public String toString() {
- return "{mSubId=" + subId + ", mIccId=" + iccId + " mSlotId=" + slotId
- + " mDisplayName=" + displayName + " mNameSource=" + nameSource
- + " mColor=" + color + " mNumber=" + number
- + " mDisplayNumberFormat=" + displayNumberFormat + " mDataRoaming=" + dataRoaming
- + " mSimIconRes=" + simIconRes + " mMcc " + mcc + " mMnc " + mnc + "}";
+ return "{id=" + mId + ", iccId=" + mIccId + " simSlotIndex=" + mSimSlotIndex
+ + " displayName=" + mDisplayName + " nameSource=" + mNameSource + " color=" + mColor
+ + " number=" + mNumber + " dataRoaming=" + mDataRoaming + " simIconRes=" + mSimIconRes
+ + " mcc " + mMcc + " mnc " + mMnc + "}";
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index edfddc7..9cd533d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -209,7 +209,7 @@ public class SubscriptionManager implements BaseColumns {
public static final int DISPLAY_NUMBER_LAST = 2;
/** @hide */
- public static final int DISLPAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;
+ public static final int DISPLAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;
/**
* TelephonyProvider column name for permission for data roaming of a SIM.
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 6837d22..94874c8 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -127,7 +127,7 @@ public class ActivityTestMain extends Activity {
@Override
public boolean onLongClick(View v) {
if (task.id >= 0 && thumbs != null) {
- mAm.removeTask(task.id, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ mAm.removeTask(task.id);
buildUi();
return true;
}
diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml
deleted file mode 100644
index c26c8ed..0000000
--- a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="833"
- android:propertyName="translateX"
- android:valueFrom="144"
- android:valueTo="144"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="100"
- android:propertyName="translateX"
- android:valueFrom="144"
- android:valueTo="147.411817411"
- android:interpolator="@interpolator/ic_open_ball_start_translatex_interpolator" />
- </set>
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="167"
- android:propertyName="translateY"
- android:valueFrom="144.58457376"
- android:valueTo="144.58457376"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="333"
- android:propertyName="translateY"
- android:valueFrom="144.58457376"
- android:valueTo="196.11111456"
- android:interpolator="@interpolator/ic_open_ball_start_translatey_interpolator_1" />
- <objectAnimator
- android:duration="333"
- android:propertyName="translateY"
- android:valueFrom="196.11111456"
- android:valueTo="196.11111456"
- android:interpolator="@interpolator/ic_open_ball_start_translatey_interpolator_2" />
- <objectAnimator
- android:duration="100"
- android:propertyName="translateY"
- android:valueFrom="196.11111456"
- android:valueTo="129.468428513"
- android:interpolator="@interpolator/ic_open_ball_start_translatey_interpolator_3" />
- </set>
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="167"
- android:propertyName="scaleX"
- android:valueFrom="0"
- android:valueTo="0.71187984"
- android:interpolator="@interpolator/ic_open_ball_start_scalex_interpolator_1" />
- <objectAnimator
- android:duration="667"
- android:propertyName="scaleX"
- android:valueFrom="0.71187984"
- android:valueTo="0.71187984"
- android:interpolator="@interpolator/ic_open_ball_start_scalex_interpolator_2" />
- <objectAnimator
- android:duration="100"
- android:propertyName="scaleX"
- android:valueFrom="0.71187984"
- android:valueTo="0.586201598553"
- android:interpolator="@interpolator/ic_open_ball_start_scalex_interpolator_3" />
- </set>
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="167"
- android:propertyName="scaleY"
- android:valueFrom="0"
- android:valueTo="0.71187984"
- android:interpolator="@interpolator/ic_open_ball_start_scaley_interpolator_1" />
- <objectAnimator
- android:duration="667"
- android:propertyName="scaleY"
- android:valueFrom="0.71187984"
- android:valueTo="0.71187984"
- android:interpolator="@interpolator/ic_open_ball_start_scaley_interpolator_2" />
- <objectAnimator
- android:duration="100"
- android:propertyName="scaleY"
- android:valueFrom="0.71187984"
- android:valueTo="0.586201598553"
- android:interpolator="@interpolator/ic_open_ball_start_scaley_interpolator_3" />
- </set>
-</set>
diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml
deleted file mode 100644
index 5096514..0000000
--- a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="933"
- android:propertyName="rotation"
- android:valueFrom="-90"
- android:valueTo="-90"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="1367"
- android:propertyName="rotation"
- android:valueFrom="-90"
- android:valueTo="-87"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml
deleted file mode 100644
index ef8496e..0000000
--- a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="500"
- android:propertyName="pathData"
- android:valueFrom="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
- android:valueTo="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="267"
- android:propertyName="pathData"
- android:valueFrom="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
- android:valueTo="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z"
- android:valueType="pathType"
- android:interpolator="@interpolator/ic_open_path_1_pathdata_interpolator_1" />
- <objectAnimator
- android:duration="33"
- android:propertyName="pathData"
- android:valueFrom="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z"
- android:valueTo="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z"
- android:valueType="pathType"
- android:interpolator="@interpolator/ic_open_path_1_pathdata_interpolator_2" />
- <objectAnimator
- android:duration="67"
- android:propertyName="pathData"
- android:valueFrom="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z"
- android:valueTo="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
- android:valueType="pathType"
- android:interpolator="@interpolator/ic_open_path_1_pathdata_interpolator_3" />
- </set>
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="933"
- android:propertyName="fillAlpha"
- android:valueFrom="1"
- android:valueTo="1"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="17"
- android:propertyName="fillAlpha"
- android:valueFrom="1"
- android:valueTo="0"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml
deleted file mode 100644
index 4961204..0000000
--- a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="917"
- android:propertyName="strokeAlpha"
- android:valueFrom="0"
- android:valueTo="0"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="17"
- android:propertyName="strokeAlpha"
- android:valueFrom="0"
- android:valueTo="1"
- android:interpolator="@android:interpolator/linear" />
- </set>
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="917"
- android:propertyName="strokeWidth"
- android:valueFrom="0"
- android:valueTo="0"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="17"
- android:propertyName="strokeWidth"
- android:valueFrom="0"
- android:valueTo="20"
- android:interpolator="@android:interpolator/linear" />
- </set>
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="933"
- android:propertyName="trimPathStart"
- android:valueFrom="0.06"
- android:valueTo="0.06"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="383"
- android:propertyName="trimPathStart"
- android:valueFrom="0.06"
- android:valueTo="0.19231"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="983"
- android:propertyName="trimPathStart"
- android:valueFrom="0.19231"
- android:valueTo="0.999"
- android:interpolator="@interpolator/ic_open_path_1_1_trimpathstart_interpolator_2" />
- </set>
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="933"
- android:propertyName="trimPathEnd"
- android:valueFrom="0.061"
- android:valueTo="0.061"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="300"
- android:propertyName="trimPathEnd"
- android:valueFrom="0.061"
- android:valueTo="0.19231"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="1067"
- android:propertyName="trimPathEnd"
- android:valueFrom="0.19231"
- android:valueTo="1"
- android:interpolator="@interpolator/ic_open_path_1_1_trimpathend_interpolator_2" />
- </set>
-</set>
diff --git a/tests/VectorDrawableTest/res/drawable/ic_open.xml b/tests/VectorDrawableTest/res/drawable/ic_open.xml
deleted file mode 100644
index ad96094..0000000
--- a/tests/VectorDrawableTest/res/drawable/ic_open.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<!-- 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:height="288dp"
- android:width="288dp"
- android:viewportHeight="288"
- android:viewportWidth="288" >
- <group
- android:name="ball_start"
- android:translateX="147.411817411"
- android:translateY="129.468428513"
- android:scaleX="0.586201598553"
- android:scaleY="0.586201598553" >
- <group
- android:name="shape_1"
- android:scaleX="0.76"
- android:scaleY="0.748114397321" >
- <path
- android:name="path_1"
- android:pathData="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
- android:fillColor="#FFFF9000"
- android:fillAlpha="0" />
- </group>
- </group>
- <group
- android:name="ball_swoop"
- android:translateX="144"
- android:translateY="144"
- android:scaleX="0.752248"
- android:scaleY="0.752248"
- android:rotation="-87.6585365854" >
- <path
- android:name="path_1_1"
- android:pathData="M -56.7679443359,1.03857421875 c 0.0,0.0 191.916503906,-13.9097290039 191.916503906,88.0704345703 c 0.0,58.4487304688 -83.6709594727,90.1372070312 -137.004882812,90.1372070312 c -82.1782226562,0.0 -177.867431641,-63.5512695312 -177.867431641,-178.207641602 c 0.0,-115.985717773 98.7650146484,-178.160949707 177.986938477,-178.160949707 c 76.2376251221,0.0 178.1640625,60.6796875 178.1640625,178.185058594 "
- android:strokeColor="#FFFF9000"
- android:strokeAlpha="1"
- android:strokeWidth="20"
- android:strokeLineCap="round"
- android:trimPathStart="0.93025"
- android:trimPathEnd="0.96248"
- android:trimPathOffset="0"
- android:fillColor="#00000000" />
- </group>
-</vector>
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml
deleted file mode 100644
index 5011ef9..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.0103034467173,0.0 0.701918866569,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml
deleted file mode 100644
index 7b0af97..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.649706648701,0.0 0.884285938423,1.92358061843 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml
deleted file mode 100644
index ea11d1f..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.353876322169,0.0 0.686452288267,-1.02094740172 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml
deleted file mode 100644
index 7bd5c49..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.754478769148,0.0 0.97,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml
deleted file mode 100644
index b0ab6e8..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.33333333,0.0 0.83333333333,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml
deleted file mode 100644
index 61060a6..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.324310863613,0.0 0.735625629425,-0.0161527278292 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml
deleted file mode 100644
index 7e19ef6..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.744517024668,0.120263649138 0.135947812437,0.994319475209 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml
deleted file mode 100644
index 1280715..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.781904890372,0.126303002187 0.188007240906,0.953418294755 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml
deleted file mode 100644
index ddf966e..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.000100000000012,0.0 0.0,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml
deleted file mode 100644
index 624e304..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 9.99999999007e-05,0.0 0.0,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml
deleted file mode 100644
index 3ebee0b..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0 0 c 0.000100000000051,0.0 0.83333333333,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
index 3045839..c4dfb84 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
@@ -26,7 +26,6 @@ public class AnimatedVectorDrawableTest extends Activity implements View.OnClick
private static final String LOGCAT = "AnimatedVectorDrawableTest";
protected int[] icon = {
- R.drawable.ic_open_animation,
R.drawable.ic_rotate_2_portrait_v2_animation,
R.drawable.ic_signal_airplane_v2_animation,
R.drawable.ic_hourglass_animation,
diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp
index f447462..848d9a1 100644
--- a/tools/aapt/AaptConfig.cpp
+++ b/tools/aapt/AaptConfig.cpp
@@ -794,4 +794,23 @@ bool isSameExcept(const ResTable_config& a, const ResTable_config& b, int axisMa
return a.diff(b) == axisMask;
}
+bool isDensityOnly(const ResTable_config& config) {
+ if (config.density == ResTable_config::DENSITY_NONE) {
+ return false;
+ }
+
+ if (config.density == ResTable_config::DENSITY_ANY) {
+ if (config.sdkVersion != SDK_L) {
+ // Someone modified the sdkVersion from the default, this is not safe to assume.
+ return false;
+ }
+ } else if (config.sdkVersion != SDK_DONUT) {
+ return false;
+ }
+
+ const uint32_t mask = ResTable_config::CONFIG_DENSITY | ResTable_config::CONFIG_VERSION;
+ const ConfigDescription nullConfig;
+ return (nullConfig.diff(config) & ~mask) == 0;
+}
+
} // namespace AaptConfig
diff --git a/tools/aapt/AaptConfig.h b/tools/aapt/AaptConfig.h
index 2963539..f73a508 100644
--- a/tools/aapt/AaptConfig.h
+++ b/tools/aapt/AaptConfig.h
@@ -80,6 +80,12 @@ android::String8 getVersion(const android::ResTable_config& config);
*/
bool isSameExcept(const android::ResTable_config& a, const android::ResTable_config& b, int configMask);
+/**
+ * Returns true if the configuration only has the density specified. In the case
+ * of 'anydpi', the version is ignored.
+ */
+bool isDensityOnly(const android::ResTable_config& config);
+
} // namespace AaptConfig
#endif // __AAPT_CONFIG_H
diff --git a/tools/aapt/AaptUtil.h b/tools/aapt/AaptUtil.h
index 47a704a..89e1ee8 100644
--- a/tools/aapt/AaptUtil.h
+++ b/tools/aapt/AaptUtil.h
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-#ifndef __AAPT_UTIL_H
-#define __AAPT_UTIL_H
+#ifndef H_AAPT_UTIL
+#define H_AAPT_UTIL
+#include <utils/KeyedVector.h>
+#include <utils/SortedVector.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -25,6 +27,38 @@ namespace AaptUtil {
android::Vector<android::String8> split(const android::String8& str, const char sep);
android::Vector<android::String8> splitAndLowerCase(const android::String8& str, const char sep);
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::Vector<VALUE> >& keyedVector,
+ const KEY& key, const VALUE& value);
+
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::SortedVector<VALUE> >& keyedVector,
+ const KEY& key, const VALUE& value);
+
+//
+// Implementations
+//
+
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::Vector<VALUE> >& keyedVector,
+ const KEY& key, const VALUE& value) {
+ ssize_t idx = keyedVector.indexOfKey(key);
+ if (idx < 0) {
+ idx = keyedVector.add(key, android::Vector<VALUE>());
+ }
+ keyedVector.editValueAt(idx).add(value);
+}
+
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::SortedVector<VALUE> >& keyedVector,
+ const KEY& key, const VALUE& value) {
+ ssize_t idx = keyedVector.indexOfKey(key);
+ if (idx < 0) {
+ idx = keyedVector.add(key, android::SortedVector<VALUE>());
+ }
+ keyedVector.editValueAt(idx).add(value);
+}
+
} // namespace AaptUtil
-#endif // __AAPT_UTIL_H
+#endif // H_AAPT_UTIL
diff --git a/tools/aapt/AaptXml.cpp b/tools/aapt/AaptXml.cpp
index 708e405..b04a55d 100644
--- a/tools/aapt/AaptXml.cpp
+++ b/tools/aapt/AaptXml.cpp
@@ -41,7 +41,7 @@ static String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrInd
}
size_t len;
- const uint16_t* str = tree.getAttributeStringValue(attrIndex, &len);
+ const char16_t* str = tree.getAttributeStringValue(attrIndex, &len);
return str ? String8(str, len) : String8();
}
@@ -103,7 +103,7 @@ String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree,
if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
if (value.dataType == Res_value::TYPE_STRING) {
size_t len;
- const uint16_t* str = tree.getAttributeStringValue(idx, &len);
+ const char16_t* str = tree.getAttributeStringValue(idx, &len);
return str ? String8(str, len) : String8();
}
resTable.resolveReference(&value, 0);
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 2cbabe1..bc9c1f7 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -33,20 +33,20 @@ aaptSources := \
Command.cpp \
CrunchCache.cpp \
FileFinder.cpp \
+ Images.cpp \
Package.cpp \
- StringPool.cpp \
- XMLNode.cpp \
+ pseudolocalize.cpp \
+ qsort_r_compat.c \
+ Resource.cpp \
ResourceFilter.cpp \
ResourceIdCache.cpp \
ResourceTable.cpp \
- Images.cpp \
- Resource.cpp \
- pseudolocalize.cpp \
SourcePos.cpp \
+ StringPool.cpp \
WorkQueue.cpp \
+ XMLNode.cpp \
ZipEntry.cpp \
- ZipFile.cpp \
- qsort_r_compat.c
+ ZipFile.cpp
aaptTests := \
tests/AaptConfig_test.cpp \
@@ -88,16 +88,13 @@ endif
include $(CLEAR_VARS)
LOCAL_MODULE := libaapt
-
-LOCAL_SRC_FILES := $(aaptSources)
-LOCAL_C_INCLUDES += $(aaptCIncludes)
-
-LOCAL_CFLAGS += -Wno-format-y2k
-LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
-LOCAL_CFLAGS += $(aaptCFlags)
+LOCAL_CFLAGS += -Wno-format-y2k -DSTATIC_ANDROIDFW_FOR_TOOLS $(aaptCFlags)
+LOCAL_CPPFLAGS += $(aaptCppFlags)
ifeq (darwin,$(HOST_OS))
LOCAL_CFLAGS += -D_DARWIN_UNLIMITED_STREAMS
endif
+LOCAL_C_INCLUDES += $(aaptCIncludes)
+LOCAL_SRC_FILES := $(aaptSources)
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -108,15 +105,11 @@ include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := aapt
-
-LOCAL_SRC_FILES := $(aaptMain)
-
-LOCAL_STATIC_LIBRARIES += \
- libaapt \
- $(aaptHostStaticLibs)
-
-LOCAL_LDLIBS += $(aaptHostLdLibs)
LOCAL_CFLAGS += $(aaptCFlags)
+LOCAL_CPPFLAGS += $(aaptCppFlags)
+LOCAL_LDLIBS += $(aaptHostLdLibs)
+LOCAL_SRC_FILES := $(aaptMain)
+LOCAL_STATIC_LIBRARIES += libaapt $(aaptHostStaticLibs)
include $(BUILD_HOST_EXECUTABLE)
@@ -127,16 +120,12 @@ include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := libaapt_tests
-
+LOCAL_CFLAGS += $(aaptCFlags)
+LOCAL_CPPFLAGS += $(aaptCppFlags)
+LOCAL_LDLIBS += $(aaptHostLdLibs)
LOCAL_SRC_FILES += $(aaptTests)
LOCAL_C_INCLUDES += $(LOCAL_PATH)
-
-LOCAL_STATIC_LIBRARIES += \
- libaapt \
- $(aaptHostStaticLibs)
-
-LOCAL_LDLIBS += $(aaptHostLdLibs)
-LOCAL_CFLAGS += $(aaptCFlags)
+LOCAL_STATIC_LIBRARIES += libaapt $(aaptHostStaticLibs)
include $(BUILD_HOST_NATIVE_TEST)
@@ -148,13 +137,12 @@ ifneq ($(SDK_ONLY),true)
include $(CLEAR_VARS)
LOCAL_MODULE := aapt
-
+LOCAL_CFLAGS += $(aaptCFlags)
LOCAL_SRC_FILES := $(aaptSources) $(aaptMain)
LOCAL_C_INCLUDES += \
$(aaptCIncludes) \
bionic \
external/stlport/stlport
-
LOCAL_SHARED_LIBRARIES := \
libandroidfw \
libutils \
@@ -162,14 +150,10 @@ LOCAL_SHARED_LIBRARIES := \
libpng \
liblog \
libz
-
LOCAL_STATIC_LIBRARIES := \
libstlport_static \
libexpat_static
-LOCAL_CFLAGS += $(aaptCFlags)
-LOCAL_CPPFLAGS += -Wno-non-virtual-dtor
-
include $(BUILD_EXECUTABLE)
endif # Not SDK_ONLY
diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h
index efb2453..fade53a 100644
--- a/tools/aapt/CacheUpdater.h
+++ b/tools/aapt/CacheUpdater.h
@@ -30,6 +30,8 @@ using namespace android;
*/
class CacheUpdater {
public:
+ virtual ~CacheUpdater() {}
+
// Make sure all the directories along this path exist
virtual void ensureDirectoriesExist(String8 path) = 0;
@@ -107,4 +109,4 @@ private:
Bundle* bundle;
};
-#endif // CACHE_UPDATER_H \ No newline at end of file
+#endif // CACHE_UPDATER_H
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 2857b59..18b8e1e 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -11,9 +11,9 @@
#include <utils/List.h>
#include <utils/Errors.h>
-#include <stdlib.h>
+#include <cstdlib>
#include <getopt.h>
-#include <assert.h>
+#include <cassert>
using namespace android;
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index a4c9dab..0d8db13 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -4,6 +4,7 @@
// Build resource files from raw assets.
//
#include "AaptAssets.h"
+#include "AaptUtil.h"
#include "AaptXml.h"
#include "CacheUpdater.h"
#include "CrunchCache.h"
@@ -13,9 +14,12 @@
#include "Main.h"
#include "ResourceTable.h"
#include "StringPool.h"
+#include "Symbol.h"
#include "WorkQueue.h"
#include "XMLNode.h"
+#include <algorithm>
+
#if HAVE_PRINTF_ZD
# define ZD "%zd"
# define ZD_TYPE ssize_t
@@ -261,7 +265,7 @@ static status_t parsePackage(Bundle* bundle, const sp<AaptAssets>& assets,
ssize_t minSdkIndex = block.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE,
"minSdkVersion");
if (minSdkIndex >= 0) {
- const uint16_t* minSdk16 = block.getAttributeStringValue(minSdkIndex, &len);
+ const char16_t* minSdk16 = block.getAttributeStringValue(minSdkIndex, &len);
const char* minSdk8 = strdup(String8(minSdk16).string());
bundle->setManifestMinSdkVersion(minSdk8);
}
@@ -450,7 +454,7 @@ static int validateAttr(const String8& path, const ResTable& table,
size_t len;
ssize_t index = parser.indexOfAttribute(ns, attr);
- const uint16_t* str;
+ const char16_t* str;
Res_value value;
if (index >= 0 && parser.getAttributeValue(index, &value) >= 0) {
const ResStringPool* pool = &parser.getStrings();
@@ -503,7 +507,7 @@ static int validateAttr(const String8& path, const ResTable& table,
}
if (validChars) {
for (size_t i=0; i<len; i++) {
- uint16_t c = str[i];
+ char16_t c = str[i];
const char* p = validChars;
bool okay = false;
while (*p) {
@@ -1550,6 +1554,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
// Re-flatten because we may have added new resource IDs
// --------------------------------------------------------------
+
ResTable finalResTable;
sp<AaptFile> resFile;
@@ -1560,6 +1565,13 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
return err;
}
+ KeyedVector<Symbol, Vector<SymbolDefinition> > densityVaryingResources;
+ if (builder->getSplits().size() > 1) {
+ // Only look for density varying resources if we're generating
+ // splits.
+ table.getDensityVaryingResources(densityVaryingResources);
+ }
+
Vector<sp<ApkSplit> >& splits = builder->getSplits();
const size_t numSplits = splits.size();
for (size_t i = 0; i < numSplits; i++) {
@@ -1583,6 +1595,63 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
return err;
}
} else {
+ ResTable resTable;
+ err = resTable.add(flattenedTable->getData(), flattenedTable->getSize());
+ if (err != NO_ERROR) {
+ fprintf(stderr, "Generated resource table for split '%s' is corrupt.\n",
+ split->getPrintableName().string());
+ return err;
+ }
+
+ bool hasError = false;
+ const std::set<ConfigDescription>& splitConfigs = split->getConfigs();
+ for (std::set<ConfigDescription>::const_iterator iter = splitConfigs.begin();
+ iter != splitConfigs.end();
+ ++iter) {
+ const ConfigDescription& config = *iter;
+ if (AaptConfig::isDensityOnly(config)) {
+ // Each density only split must contain all
+ // density only resources.
+ Res_value val;
+ resTable.setParameters(&config);
+ const size_t densityVaryingResourceCount = densityVaryingResources.size();
+ for (size_t k = 0; k < densityVaryingResourceCount; k++) {
+ const Symbol& symbol = densityVaryingResources.keyAt(k);
+ ssize_t block = resTable.getResource(symbol.id, &val, true);
+ if (block < 0) {
+ // Maybe it's in the base?
+ finalResTable.setParameters(&config);
+ block = finalResTable.getResource(symbol.id, &val, true);
+ }
+
+ if (block < 0) {
+ hasError = true;
+ SourcePos().error("%s has no definition for density split '%s'",
+ symbol.toString().string(), config.toString().string());
+
+ if (bundle->getVerbose()) {
+ const Vector<SymbolDefinition>& defs = densityVaryingResources[k];
+ const size_t defCount = std::min(size_t(5), defs.size());
+ for (size_t d = 0; d < defCount; d++) {
+ const SymbolDefinition& def = defs[d];
+ def.source.error("%s has definition for %s",
+ symbol.toString().string(), def.config.toString().string());
+ }
+
+ if (defCount < defs.size()) {
+ SourcePos().error("and %d more ...", (int) (defs.size() - defCount));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (hasError) {
+ return UNKNOWN_ERROR;
+ }
+
+ // Generate the AndroidManifest for this split.
sp<AaptFile> generatedManifest = new AaptFile(String8("AndroidManifest.xml"),
AaptGroupEntry(), String8());
err = generateAndroidManifestForSplit(bundle, assets, split,
@@ -1710,7 +1779,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
}
size_t len;
ssize_t index = block.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, "name");
- const uint16_t* id = block.getAttributeStringValue(index, &len);
+ const char16_t* id = block.getAttributeStringValue(index, &len);
if (id == NULL) {
fprintf(stderr, "%s:%d: missing name attribute in element <%s>.\n",
manifestPath.string(), block.getLineNumber(),
@@ -1753,7 +1822,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
hasErrors = true;
}
syms->addStringSymbol(String8(e), idStr, srcPos);
- const uint16_t* cmt = block.getComment(&len);
+ const char16_t* cmt = block.getComment(&len);
if (cmt != NULL && *cmt != 0) {
//printf("Comment of %s: %s\n", String8(e).string(),
// String8(cmt).string());
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 4587a4b..beff604 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -6,6 +6,7 @@
#include "ResourceTable.h"
+#include "AaptUtil.h"
#include "XMLNode.h"
#include "ResourceFilter.h"
#include "ResourceIdCache.h"
@@ -399,7 +400,7 @@ static status_t compileAttribute(const sp<AaptFile>& in,
ssize_t l10nIdx = block.indexOfAttribute(NULL, "localization");
if (l10nIdx >= 0) {
- const uint16_t* str = block.getAttributeStringValue(l10nIdx, &len);
+ const char16_t* str = block.getAttributeStringValue(l10nIdx, &len);
bool error;
uint32_t l10n_required = parse_flags(str, len, l10nRequiredFlags, &error);
if (error) {
@@ -1325,7 +1326,7 @@ status_t compileResourceFile(Bundle* bundle,
size_t n = block.getAttributeCount();
for (size_t i = 0; i < n; i++) {
size_t length;
- const uint16_t* attr = block.getAttributeName(i, &length);
+ const char16_t* attr = block.getAttributeName(i, &length);
if (strcmp16(attr, name16.string()) == 0) {
name.setTo(block.getAttributeStringValue(i, &length));
} else if (strcmp16(attr, translatable16.string()) == 0) {
@@ -1441,14 +1442,14 @@ status_t compileResourceFile(Bundle* bundle,
// translatable.
for (size_t i = 0; i < n; i++) {
size_t length;
- const uint16_t* attr = block.getAttributeName(i, &length);
+ const char16_t* attr = block.getAttributeName(i, &length);
if (strcmp16(attr, formatted16.string()) == 0) {
- const uint16_t* value = block.getAttributeStringValue(i, &length);
+ const char16_t* value = block.getAttributeStringValue(i, &length);
if (strcmp16(value, false16.string()) == 0) {
curIsFormatted = false;
}
} else if (strcmp16(attr, translatable16.string()) == 0) {
- const uint16_t* value = block.getAttributeStringValue(i, &length);
+ const char16_t* value = block.getAttributeStringValue(i, &length);
if (strcmp16(value, false16.string()) == 0) {
isTranslatable = false;
}
@@ -4486,3 +4487,34 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
return NO_ERROR;
}
+
+void ResourceTable::getDensityVaryingResources(KeyedVector<Symbol, Vector<SymbolDefinition> >& resources) {
+ const ConfigDescription nullConfig;
+
+ const size_t packageCount = mOrderedPackages.size();
+ for (size_t p = 0; p < packageCount; p++) {
+ const Vector<sp<Type> >& types = mOrderedPackages[p]->getOrderedTypes();
+ const size_t typeCount = types.size();
+ for (size_t t = 0; t < typeCount; t++) {
+ const Vector<sp<ConfigList> >& configs = types[t]->getOrderedConfigs();
+ const size_t configCount = configs.size();
+ for (size_t c = 0; c < configCount; c++) {
+ const DefaultKeyedVector<ConfigDescription, sp<Entry> >& configEntries = configs[c]->getEntries();
+ const size_t configEntryCount = configEntries.size();
+ for (size_t ce = 0; ce < configEntryCount; ce++) {
+ const ConfigDescription& config = configEntries.keyAt(ce);
+ if (AaptConfig::isDensityOnly(config)) {
+ // This configuration only varies with regards to density.
+ const Symbol symbol(mOrderedPackages[p]->getName(),
+ types[t]->getName(),
+ configs[c]->getName(),
+ getResId(mOrderedPackages[p], types[t], configs[c]->getEntryIndex()));
+
+ const sp<Entry>& entry = configEntries.valueAt(ce);
+ AaptUtil::appendValue(resources, symbol, SymbolDefinition(symbol, config, entry->getPos()));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index eac5dd3..db392c8 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -7,15 +7,16 @@
#ifndef RESOURCE_TABLE_H
#define RESOURCE_TABLE_H
-#include "ConfigDescription.h"
-#include "StringPool.h"
-#include "SourcePos.h"
-#include "ResourceFilter.h"
-
#include <map>
#include <queue>
#include <set>
+#include "ConfigDescription.h"
+#include "ResourceFilter.h"
+#include "SourcePos.h"
+#include "StringPool.h"
+#include "Symbol.h"
+
using namespace std;
class XMLNode;
@@ -543,6 +544,8 @@ public:
DefaultKeyedVector<String16, uint32_t> mKeyStringsMapping;
};
+ void getDensityVaryingResources(KeyedVector<Symbol, Vector<SymbolDefinition> >& resources);
+
private:
void writePublicDefinitions(const String16& package, FILE* fp, bool pub);
sp<Package> getPackage(const String16& package);
diff --git a/tools/aapt/SourcePos.cpp b/tools/aapt/SourcePos.cpp
index ae25047..3864320 100644
--- a/tools/aapt/SourcePos.cpp
+++ b/tools/aapt/SourcePos.cpp
@@ -141,6 +141,12 @@ SourcePos::printf(const char* fmt, ...) const
}
bool
+SourcePos::operator<(const SourcePos& rhs) const
+{
+ return (file < rhs.file) || (line < rhs.line);
+}
+
+bool
SourcePos::hasErrors()
{
return g_errors.size() > 0;
diff --git a/tools/aapt/SourcePos.h b/tools/aapt/SourcePos.h
index 4ce817f..13cfb9d 100644
--- a/tools/aapt/SourcePos.h
+++ b/tools/aapt/SourcePos.h
@@ -21,6 +21,8 @@ public:
void warning(const char* fmt, ...) const;
void printf(const char* fmt, ...) const;
+ bool operator<(const SourcePos& rhs) const;
+
static bool hasErrors();
static void printErrors(FILE* to);
};
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index 06769e4..2727b3d 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -21,7 +21,8 @@
#define NOISY(x) //x
-void strcpy16_htod(uint16_t* dst, const uint16_t* src)
+#if __cplusplus >= 201103L
+void strcpy16_htod(char16_t* dst, const char16_t* src)
{
while (*src) {
char16_t s = htods(*src);
@@ -30,6 +31,17 @@ void strcpy16_htod(uint16_t* dst, const uint16_t* src)
}
*dst = 0;
}
+#endif
+
+void strcpy16_htod(uint16_t* dst, const char16_t* src)
+{
+ while (*src) {
+ uint16_t s = htods(static_cast<uint16_t>(*src));
+ *dst++ = s;
+ src++;
+ }
+ *dst = 0;
+}
void printStringPool(const ResStringPool* pool)
{
@@ -416,7 +428,7 @@ status_t StringPool::writeStringBlock(const sp<AaptFile>& pool)
return NO_MEMORY;
}
- const size_t charSize = mUTF8 ? sizeof(uint8_t) : sizeof(char16_t);
+ const size_t charSize = mUTF8 ? sizeof(uint8_t) : sizeof(uint16_t);
size_t strPos = 0;
for (i=0; i<STRINGS; i++) {
diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h
index 1b3abfd..a9c7bec 100644
--- a/tools/aapt/StringPool.h
+++ b/tools/aapt/StringPool.h
@@ -26,7 +26,10 @@ using namespace android;
#define PRINT_STRING_METRICS 0
-void strcpy16_htod(uint16_t* dst, const uint16_t* src);
+#if __cplusplus >= 201103L
+void strcpy16_htod(char16_t* dst, const char16_t* src);
+#endif
+void strcpy16_htod(uint16_t* dst, const char16_t* src);
void printStringPool(const ResStringPool* pool);
diff --git a/tools/aapt/Symbol.h b/tools/aapt/Symbol.h
new file mode 100644
index 0000000..e157541
--- /dev/null
+++ b/tools/aapt/Symbol.h
@@ -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.
+ */
+
+#ifndef AAPT_SYMBOL_H
+#define AAPT_SYMBOL_H
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+#include "ConfigDescription.h"
+#include "SourcePos.h"
+
+/**
+ * A resource symbol, not attached to any configuration or context.
+ */
+struct Symbol {
+ inline Symbol();
+ inline Symbol(const android::String16& p, const android::String16& t, const android::String16& n, uint32_t i);
+ inline android::String8 toString() const;
+ inline bool operator<(const Symbol& rhs) const;
+
+ android::String16 package;
+ android::String16 type;
+ android::String16 name;
+ uint32_t id;
+
+};
+
+/**
+ * A specific defintion of a symbol, defined with a configuration and a definition site.
+ */
+struct SymbolDefinition {
+ inline SymbolDefinition();
+ inline SymbolDefinition(const Symbol& s, const ConfigDescription& c, const SourcePos& src);
+ inline bool operator<(const SymbolDefinition& rhs) const;
+
+ Symbol symbol;
+ ConfigDescription config;
+ SourcePos source;
+};
+
+//
+// Implementations
+//
+
+Symbol::Symbol() {
+}
+
+Symbol::Symbol(const android::String16& p, const android::String16& t, const android::String16& n, uint32_t i)
+ : package(p)
+ , type(t)
+ , name(n)
+ , id(i) {
+}
+
+android::String8 Symbol::toString() const {
+ return android::String8::format("%s:%s/%s (0x%08x)",
+ android::String8(package).string(),
+ android::String8(type).string(),
+ android::String8(name).string(),
+ (int) id);
+}
+
+bool Symbol::operator<(const Symbol& rhs) const {
+ return (package < rhs.package) || (type < rhs.type) || (name < rhs.name) || (id < rhs.id);
+}
+
+SymbolDefinition::SymbolDefinition() {
+}
+
+SymbolDefinition::SymbolDefinition(const Symbol& s, const ConfigDescription& c, const SourcePos& src)
+ : symbol(s)
+ , config(c)
+ , source(src) {
+}
+
+bool SymbolDefinition::operator<(const SymbolDefinition& rhs) const {
+ return (symbol < rhs.symbol) || (config < rhs.config) || (source < rhs.source);
+}
+
+#endif // AAPT_SYMBOL_H
+
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 51a4154..899fb63 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -234,9 +234,9 @@ status_t parseStyledString(Bundle* bundle,
const String8 element8(element16);
size_t nslen;
- const uint16_t* ns = inXml->getElementNamespace(&nslen);
+ const char16_t* ns = inXml->getElementNamespace(&nslen);
if (ns == NULL) {
- ns = (const uint16_t*)"\0\0";
+ ns = (const char16_t*)"\0\0";
nslen = 0;
}
const String8 nspace(String16(ns, nslen));
@@ -291,9 +291,9 @@ moveon:
} else if (code == ResXMLTree::END_TAG) {
size_t nslen;
- const uint16_t* ns = inXml->getElementNamespace(&nslen);
+ const char16_t* ns = inXml->getElementNamespace(&nslen);
if (ns == NULL) {
- ns = (const uint16_t*)"\0\0";
+ ns = (const char16_t*)"\0\0";
nslen = 0;
}
const String8 nspace(String16(ns, nslen));
@@ -422,7 +422,7 @@ static String8 make_prefix(int depth)
}
static String8 build_namespace(const Vector<namespace_entry>& namespaces,
- const uint16_t* ns)
+ const char16_t* ns)
{
String8 str;
if (ns != NULL) {
@@ -453,9 +453,9 @@ void printXMLBlock(ResXMLTree* block)
int i;
if (code == ResXMLTree::START_TAG) {
size_t len;
- const uint16_t* ns16 = block->getElementNamespace(&len);
+ const char16_t* ns16 = block->getElementNamespace(&len);
String8 elemNs = build_namespace(namespaces, ns16);
- const uint16_t* com16 = block->getComment(&len);
+ const char16_t* com16 = block->getComment(&len);
if (com16) {
printf("%s <!-- %s -->\n", prefix.string(), String8(com16).string());
}
@@ -503,7 +503,7 @@ void printXMLBlock(ResXMLTree* block)
} else if (code == ResXMLTree::START_NAMESPACE) {
namespace_entry ns;
size_t len;
- const uint16_t* prefix16 = block->getNamespacePrefix(&len);
+ const char16_t* prefix16 = block->getNamespacePrefix(&len);
if (prefix16) {
ns.prefix = String8(prefix16);
} else {
@@ -518,7 +518,7 @@ void printXMLBlock(ResXMLTree* block)
depth--;
const namespace_entry& ns = namespaces.top();
size_t len;
- const uint16_t* prefix16 = block->getNamespacePrefix(&len);
+ const char16_t* prefix16 = block->getNamespacePrefix(&len);
String8 pr;
if (prefix16) {
pr = String8(prefix16);
diff --git a/tools/layoutlib/bridge/src/android/view/WindowCallback.java b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
new file mode 100644
index 0000000..78242a8
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
@@ -0,0 +1,131 @@
+/*
+ * 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.view;
+
+import android.view.ActionMode.Callback;
+import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * An empty implementation of {@link Window.Callback} that always returns null/false.
+ */
+public class WindowCallback implements Window.Callback {
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean dispatchTrackballEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ return false;
+ }
+
+ @Override
+ public View onCreatePanelView(int featureId) {
+ return null;
+ }
+
+ @Override
+ public boolean onCreatePanelMenu(int featureId, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onPreparePanel(int featureId, View view, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onMenuOpened(int featureId, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public void onWindowAttributesChanged(LayoutParams attrs) {
+
+ }
+
+ @Override
+ public void onContentChanged() {
+
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+
+ }
+
+ @Override
+ public void onPanelClosed(int featureId, Menu menu) {
+
+ }
+
+ @Override
+ public boolean onSearchRequested() {
+ return false;
+ }
+
+ @Override
+ public ActionMode onWindowStartingActionMode(Callback callback) {
+ return null;
+ }
+
+ @Override
+ public void onActionModeStarted(ActionMode mode) {
+
+ }
+
+ @Override
+ public void onActionModeFinished(ActionMode mode) {
+
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java b/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java
new file mode 100644
index 0000000..fdd1779
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java
@@ -0,0 +1,32 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+
+/**
+ * To access non public members of classes in {@link Toolbar}
+ */
+public class Toolbar_Accessor {
+ public static ActionMenuPresenter getActionMenuPresenter(Toolbar toolbar) {
+ return toolbar.getOuterActionMenuPresenter();
+ }
+
+ public static Context getPopupContext(Toolbar toolbar) {
+ return toolbar.getPopupContext();
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 825731b..ec78712 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -19,6 +19,7 @@ package com.android.layoutlib.bridge;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
+import com.android.annotations.NonNull;
import com.android.ide.common.rendering.api.Capability;
import com.android.ide.common.rendering.api.DrawableParams;
import com.android.ide.common.rendering.api.LayoutLog;
@@ -459,7 +460,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
public static void setLog(LayoutLog log) {
// check only the thread currently owning the lock can do this.
- if (sLock.isHeldByCurrentThread() == false) {
+ if (!sLock.isHeldByCurrentThread()) {
throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
}
@@ -489,7 +490,6 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
/**
* Returns the name of a framework resource whose value is an int array.
- * @param array
*/
public static String resolveResourceId(int[] array) {
sIntArrayWrapper.set(array);
@@ -502,6 +502,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
* @param name the name of the resource.
* @return an {@link Integer} containing the resource id, or null if no resource were found.
*/
+ @NonNull
public static Integer getResourceId(ResourceType type, String name) {
Map<String, Integer> map = sRevRMap.get(type);
Integer value = null;
@@ -509,11 +510,8 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
value = map.get(name);
}
- if (value == null) {
- value = sDynamicIds.getId(type, name);
- }
+ return value == null ? sDynamicIds.getId(type, name) : value;
- return value;
}
/**
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index d804230..3d3afa4 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -52,7 +52,6 @@ import android.content.res.BridgeTypedArray;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
@@ -127,7 +126,6 @@ public final class BridgeContext extends Context {
* @param metrics the {@link DisplayMetrics}.
* @param renderResources the configured resources (both framework and projects) for this
* render.
- * @param projectCallback
* @param config the Configuration object for this render.
* @param targetSdkVersion the targetSdkVersion of the application.
*/
@@ -331,7 +329,7 @@ public final class BridgeContext extends Context {
boolean attachToRoot, boolean skipCallbackParser) {
boolean isPlatformLayout = resource.isFramework();
- if (isPlatformLayout == false && skipCallbackParser == false) {
+ if (!isPlatformLayout && !skipCallbackParser) {
// check if the project callback can provide us with a custom parser.
ILayoutPullParser parser = getParser(resource);
@@ -663,7 +661,7 @@ public final class BridgeContext extends Context {
}
String attrName = attribute.getFirst();
- boolean frameworkAttr = attribute.getSecond().booleanValue();
+ boolean frameworkAttr = attribute.getSecond();
String value = null;
if (set != null) {
value = set.getAttributeValue(
@@ -672,7 +670,7 @@ public final class BridgeContext extends Context {
// if this is an app attribute, and the first get fails, try with the
// new res-auto namespace as well
- if (frameworkAttr == false && value == null) {
+ if (!frameworkAttr && value == null) {
value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
}
}
@@ -789,13 +787,13 @@ public final class BridgeContext extends Context {
List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length);
// for each attribute, get its name so that we can search it in the style
- for (int i = 0 ; i < attrs.length ; i++) {
- Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]);
+ for (int attr : attrs) {
+ Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attr);
boolean isFramework = false;
if (resolvedResource != null) {
isFramework = true;
} else {
- resolvedResource = mProjectCallback.resolveResourceId(attrs[i]);
+ resolvedResource = mProjectCallback.resolveResourceId(attr);
}
if (resolvedResource != null) {
@@ -841,7 +839,7 @@ public final class BridgeContext extends Context {
if (id == null) {
// generate a new id
- id = Integer.valueOf(++mDynamicIdGenerator);
+ id = ++mDynamicIdGenerator;
// and add it to the maps.
mDynamicIdToStyleMap.put(id, resValue);
@@ -860,19 +858,24 @@ public final class BridgeContext extends Context {
}
public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) {
- Integer value = Bridge.getResourceId(resType, resName);
- if (value != null) {
- return value.intValue();
+ if (getRenderResources().getFrameworkResource(resType, resName) != null) {
+ // Bridge.getResourceId creates a new resource id if an existing one isn't found. So,
+ // we check for the existence of the resource before calling it.
+ return Bridge.getResourceId(resType, resName);
}
return defValue;
}
public int getProjectResourceValue(ResourceType resType, String resName, int defValue) {
- if (mProjectCallback != null) {
- Integer value = mProjectCallback.getResourceId(resType, resName);
- if (value != null) {
- return value.intValue();
+ // getResourceId creates a new resource id if an existing resource id isn't found. So, we
+ // check for the existence of the resource before calling it.
+ if (getRenderResources().getProjectResource(resType, resName) != null) {
+ if (mProjectCallback != null) {
+ Integer value = mProjectCallback.getResourceId(resType, resName);
+ if (value != null) {
+ return value;
+ }
}
}
@@ -1455,9 +1458,6 @@ public final class BridgeContext extends Context {
return null;
}
- /**
- * @hide
- */
@Override
public int getUserId() {
return 0; // not used
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
index d95c815..57fd68e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
@@ -18,36 +18,24 @@ package com.android.layoutlib.bridge.bars;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
-import com.android.ide.common.rendering.api.ActionBarCallback;
-import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
-import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.SessionParams;
import com.android.internal.R;
-import com.android.internal.app.WindowDecorActionBar;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.widget.ActionBarAccessor;
-import com.android.internal.widget.ActionBarContainer;
-import com.android.internal.widget.ActionBarView;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.resources.ResourceType;
-import android.app.ActionBar;
-import android.app.ActionBar.Tab;
-import android.app.ActionBar.TabListener;
-import android.app.FragmentTransaction;
import android.content.Context;
import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.util.TypedValue;
-import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.MenuInflater;
import android.view.View;
+import android.view.View.MeasureSpec;
import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ActionMenuPresenter;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
@@ -56,172 +44,72 @@ import android.widget.RelativeLayout;
import java.util.ArrayList;
-/**
- * A layout representing the action bar.
- */
-public class ActionBarLayout extends LinearLayout {
+public class ActionBarLayout {
+
+ private static final String LAYOUT_ATTR_NAME = "windowActionBarFullscreenDecorLayout";
+
+ // The Action Bar
+ @NonNull private CustomActionBarWrapper mActionBar;
// Store another reference to the context so that we don't have to cast it repeatedly.
@NonNull private final BridgeContext mBridgeContext;
- @NonNull private final Context mThemedContext;
-
- @NonNull private final ActionBar mActionBar;
-
- // Data for Action Bar.
- @Nullable private final String mIcon;
- @Nullable private final String mTitle;
- @Nullable private final String mSubTitle;
- private final boolean mSplit;
- private final boolean mShowHomeAsUp;
- private final int mNavMode;
-
- // Helper fields.
- @NonNull private final MenuBuilder mMenuBuilder;
- private final int mPopupMaxWidth;
- @NonNull private final RenderResources res;
- @Nullable private final ActionBarView mActionBarView;
- @Nullable private FrameLayout mContentRoot;
- @NonNull private final ActionBarCallback mCallback;
+
+ @NonNull private FrameLayout mContentRoot;
// A fake parent for measuring views.
@Nullable private ViewGroup mMeasureParent;
- public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params) {
-
- super(context);
- setOrientation(LinearLayout.HORIZONTAL);
- setGravity(Gravity.CENTER_VERTICAL);
-
- // Inflate action bar layout.
- LayoutInflater.from(context).inflate(R.layout.screen_action_bar, this,
- true /*attachToRoot*/);
- mActionBar = new WindowDecorActionBar(this);
-
- // Set contexts.
- mBridgeContext = context;
- mThemedContext = mActionBar.getThemedContext();
-
- // Set data for action bar.
- mCallback = params.getProjectCallback().getActionBarCallback();
- mIcon = params.getAppIcon();
- mTitle = params.getAppLabel();
- // Split Action Bar when the screen size is narrow and the application requests split action
- // bar when narrow.
- mSplit = context.getResources().getBoolean(R.bool.split_action_bar_is_narrow) &&
- mCallback.getSplitActionBarWhenNarrow();
- mNavMode = mCallback.getNavigationMode();
- // TODO: Support Navigation Drawer Indicator.
- mShowHomeAsUp = mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP;
- mSubTitle = mCallback.getSubTitle();
-
-
- // Set helper fields.
- mMenuBuilder = new MenuBuilder(mThemedContext);
- res = mBridgeContext.getRenderResources();
- mPopupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
- mThemedContext.getResources().getDimensionPixelSize(
- R.dimen.config_prefDialogWidth));
- mActionBarView = (ActionBarView) findViewById(R.id.action_bar);
- mContentRoot = (FrameLayout) findViewById(android.R.id.content);
-
- setupActionBar();
- }
-
/**
- * Sets up the action bar by filling the appropriate data.
+ * Inflate the action bar and attach it to {@code parentView}
*/
- private void setupActionBar() {
- // Add title and sub title.
- ResourceValue titleValue = res.findResValue(mTitle, false /*isFramework*/);
- if (titleValue != null && titleValue.getValue() != null) {
- mActionBar.setTitle(titleValue.getValue());
- } else {
- mActionBar.setTitle(mTitle);
- }
- if (mSubTitle != null) {
- mActionBar.setSubtitle(mSubTitle);
- }
+ public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params,
+ @NonNull ViewGroup parentView) {
- // Add show home as up icon.
- if (mShowHomeAsUp) {
- mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
- }
+ mBridgeContext = context;
- // Set the navigation mode.
- mActionBar.setNavigationMode(mNavMode);
- if (mNavMode == ActionBar.NAVIGATION_MODE_TABS) {
- setupTabs(3);
+ ResourceValue layoutName = context.getRenderResources()
+ .findItemInTheme(LAYOUT_ATTR_NAME, true);
+ if (layoutName != null) {
+ // We may need to resolve the reference obtained.
+ layoutName = context.getRenderResources().findResValue(layoutName.getValue(),
+ layoutName.isFramework());
}
-
- if (mActionBarView != null) {
- // If the action bar style doesn't specify an icon, set the icon obtained from the session
- // params.
- if (!mActionBarView.hasIcon() && mIcon != null) {
- Drawable iconDrawable = getDrawable(mIcon, false /*isFramework*/);
- if (iconDrawable != null) {
- mActionBar.setIcon(iconDrawable);
- }
+ int layoutId = 0;
+ String error = null;
+ if (layoutName == null) {
+ error = "Unable to find action bar layout (" + LAYOUT_ATTR_NAME
+ + ") in the current theme.";
+ } else {
+ layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
+ layoutName.getName(), 0);
+ if (layoutId == 0) {
+ error = String.format("Unable to resolve attribute \"%s\" of type \"%s\"",
+ layoutName.getName(), layoutName.getResourceType());
}
-
- // Set action bar to be split, if needed.
- ActionBarContainer splitView = (ActionBarContainer) findViewById(R.id.split_action_bar);
- mActionBarView.setSplitView(splitView);
- mActionBarView.setSplitToolbar(mSplit);
-
- inflateMenus();
}
- }
-
- /**
- * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
- * adds them to the action bar.
- */
- private void inflateMenus() {
- if (mActionBarView == null) {
- return;
- }
- final MenuInflater inflater = new MenuInflater(mThemedContext);
- for (String name : mCallback.getMenuIdNames()) {
- if (mBridgeContext.getRenderResources().getProjectResource(ResourceType.MENU, name)
- != null) {
- int id = mBridgeContext.getProjectResourceValue(ResourceType.MENU, name, -1);
- if (id > -1) {
- inflater.inflate(id, mMenuBuilder);
- }
- }
+ if (layoutId == 0) {
+ throw new RuntimeException(error);
}
- mActionBarView.setMenu(mMenuBuilder, null /*callback*/);
- }
+ // Inflate action bar layout.
+ View decorContent = LayoutInflater.from(context).inflate(layoutId, parentView, true);
- // TODO: Use an adapter, like List View to set up tabs.
- private void setupTabs(int num) {
- for (int i = 1; i <= num; i++) {
- Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
- @Override
- public void onTabUnselected(Tab t, FragmentTransaction ft) {
- // pass
- }
- @Override
- public void onTabSelected(Tab t, FragmentTransaction ft) {
- // pass
- }
- @Override
- public void onTabReselected(Tab t, FragmentTransaction ft) {
- // pass
- }
- });
- mActionBar.addTab(tab);
- }
- }
+ mActionBar = CustomActionBarWrapper.getActionBarWrapper(context, params, decorContent);
- @Nullable
- private Drawable getDrawable(@NonNull String name, boolean isFramework) {
- ResourceValue value = res.findResValue(name, isFramework);
- value = res.resolveResValue(value);
- if (value != null) {
- return ResourceHelper.getDrawable(value, mBridgeContext);
+ FrameLayout contentRoot = (FrameLayout) parentView.findViewById(android.R.id.content);
+
+ // If something went wrong and we were not able to initialize the content root,
+ // just add a frame layout inside this and return.
+ if (contentRoot == null) {
+ contentRoot = new FrameLayout(context);
+ contentRoot.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT));
+ parentView.addView(contentRoot);
+ mContentRoot = contentRoot;
+ } else {
+ mContentRoot = contentRoot;
+ mActionBar.setupActionBar();
+ mActionBar.inflateMenus();
}
- return null;
}
/**
@@ -229,7 +117,7 @@ public class ActionBarLayout extends LinearLayout {
* the content frame which shall serve as the new content root.
*/
public void createMenuPopup() {
- assert mContentRoot != null && findViewById(android.R.id.content) == mContentRoot
+ assert mContentRoot.getId() == android.R.id.content
: "Action Bar Menus have already been created.";
if (!isOverflowPopupNeeded()) {
@@ -237,7 +125,7 @@ public class ActionBarLayout extends LinearLayout {
}
// Create a layout to hold the menus and the user's content.
- RelativeLayout layout = new RelativeLayout(mThemedContext);
+ RelativeLayout layout = new RelativeLayout(mActionBar.getPopupContext());
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
mContentRoot.addView(layout);
@@ -259,13 +147,14 @@ public class ActionBarLayout extends LinearLayout {
@NonNull
private View createMenuView() {
DisplayMetrics metrics = mBridgeContext.getMetrics();
- OverflowMenuAdapter adapter = new OverflowMenuAdapter(mMenuBuilder, mThemedContext);
+ MenuBuilder menu = mActionBar.getMenuBuilder();
+ OverflowMenuAdapter adapter = new OverflowMenuAdapter(menu, mActionBar.getPopupContext());
- LinearLayout layout = new LinearLayout(mThemedContext);
+ LinearLayout layout = new LinearLayout(mActionBar.getPopupContext());
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
measureContentWidth(adapter), LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_END);
- if (mSplit) {
+ if (mActionBar.isSplit()) {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
// TODO: Find correct value instead of hardcoded 10dp.
layoutParams.bottomMargin = getPixelValue("-10dp", metrics);
@@ -273,7 +162,7 @@ public class ActionBarLayout extends LinearLayout {
layoutParams.topMargin = getPixelValue("-10dp", metrics);
}
layout.setLayoutParams(layoutParams);
- final TypedArray a = mThemedContext.obtainStyledAttributes(null,
+ final TypedArray a = mActionBar.getPopupContext().obtainStyledAttributes(null,
R.styleable.PopupWindow, R.attr.popupMenuStyle, 0);
layout.setBackground(a.getDrawable(R.styleable.PopupWindow_popupBackground));
layout.setDividerDrawable(a.getDrawable(R.attr.actionBarDivider));
@@ -282,20 +171,25 @@ public class ActionBarLayout extends LinearLayout {
layout.setDividerPadding(getPixelValue("12dp", metrics));
layout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
- ListView listView = new ListView(mThemedContext, null, R.attr.dropDownListViewStyle);
+ ListView listView = new ListView(mActionBar.getPopupContext(), null,
+ R.attr.dropDownListViewStyle);
listView.setAdapter(adapter);
layout.addView(listView);
return layout;
}
private boolean isOverflowPopupNeeded() {
- boolean needed = mCallback.isOverflowPopupNeeded();
+ boolean needed = mActionBar.isOverflowPopupNeeded();
if (!needed) {
return false;
}
// Copied from android.widget.ActionMenuPresenter.updateMenuView()
- ArrayList<MenuItemImpl> menus = mMenuBuilder.getNonActionItems();
- if (ActionBarAccessor.getActionMenuPresenter(mActionBarView).isOverflowReserved() &&
+ ArrayList<MenuItemImpl> menus = mActionBar.getMenuBuilder().getNonActionItems();
+ ActionMenuPresenter presenter = mActionBar.getActionMenuPresenter();
+ if (presenter == null) {
+ throw new RuntimeException("Failed to create a Presenter for Action Bar Menus.");
+ }
+ if (presenter.isOverflowReserved() &&
menus != null) {
final int count = menus.size();
if (count == 1) {
@@ -307,7 +201,7 @@ public class ActionBarLayout extends LinearLayout {
return needed;
}
- @Nullable
+ @NonNull
public FrameLayout getContentRoot() {
return mContentRoot;
}
@@ -319,6 +213,7 @@ public class ActionBarLayout extends LinearLayout {
View itemView = null;
int itemType = 0;
+ Context context = mActionBar.getPopupContext();
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final int count = adapter.getCount();
@@ -330,15 +225,17 @@ public class ActionBarLayout extends LinearLayout {
}
if (mMeasureParent == null) {
- mMeasureParent = new FrameLayout(mThemedContext);
+ mMeasureParent = new FrameLayout(context);
}
itemView = adapter.getView(i, itemView, mMeasureParent);
itemView.measure(widthMeasureSpec, heightMeasureSpec);
final int itemWidth = itemView.getMeasuredWidth();
- if (itemWidth >= mPopupMaxWidth) {
- return mPopupMaxWidth;
+ int popupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
+ context.getResources().getDimensionPixelSize(R.dimen.config_prefDialogWidth));
+ if (itemWidth >= popupMaxWidth) {
+ return popupMaxWidth;
} else if (itemWidth > maxWidth) {
maxWidth = itemWidth;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java
new file mode 100644
index 0000000..70b9cc3
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java
@@ -0,0 +1,351 @@
+/*
+ * 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.layoutlib.bridge.bars;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.ActionBarCallback;
+import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.SessionParams;
+import com.android.internal.R;
+import com.android.internal.app.ToolbarActionBar;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.widget.ActionBarAccessor;
+import com.android.internal.widget.ActionBarView;
+import com.android.internal.widget.DecorToolbar;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowCallback;
+import android.widget.ActionMenuPresenter;
+import android.widget.Toolbar;
+import android.widget.Toolbar_Accessor;
+
+import static com.android.SdkConstants.ANDROID_NS_NAME_PREFIX;
+import static com.android.resources.ResourceType.MENU;
+
+/**
+ * A common API to access {@link ToolbarActionBar} and {@link WindowDecorActionBar}.
+ */
+public abstract class CustomActionBarWrapper {
+
+ @NonNull protected ActionBar mActionBar;
+ @NonNull protected SessionParams mParams;
+ @NonNull protected ActionBarCallback mCallback;
+ @NonNull protected BridgeContext mContext;
+
+ /**
+ * Returns a wrapper around different implementations of the Action Bar to provide a common API.
+ *
+ * @param decorContent the top level view returned by inflating
+ * ?attr/windowActionBarFullscreenDecorLayout
+ */
+ @NonNull
+ public static CustomActionBarWrapper getActionBarWrapper(@NonNull BridgeContext context,
+ @NonNull SessionParams params, @NonNull View decorContent) {
+ View view = decorContent.findViewById(R.id.action_bar);
+ if (view instanceof Toolbar) {
+ return new ToolbarWrapper(context, params, ((Toolbar) view)
+ );
+ } else if (view instanceof ActionBarView) {
+ return new WindowActionBarWrapper(context, params, decorContent, ((ActionBarView) view)
+ );
+ } else {
+ throw new IllegalStateException("Can't make an action bar out of " +
+ view.getClass().getSimpleName());
+ }
+ }
+
+ CustomActionBarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+ @NonNull ActionBar actionBar) {
+ mActionBar = actionBar;
+ mParams = params;
+ mCallback = params.getProjectCallback().getActionBarCallback();
+ mContext = context;
+ }
+
+ protected void setupActionBar() {
+ // Do the things that are common to all implementations.
+ RenderResources res = mContext.getRenderResources();
+
+ String title = mParams.getAppLabel();
+ ResourceValue titleValue = res.findResValue(title, false);
+ if (titleValue != null && titleValue.getValue() != null) {
+ mActionBar.setTitle(titleValue.getValue());
+ } else {
+ mActionBar.setTitle(title);
+ }
+
+ String subTitle = mCallback.getSubTitle();
+ if (subTitle != null) {
+ mActionBar.setSubtitle(subTitle);
+ }
+
+ // Add show home as up icon.
+ if (mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP) {
+ mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
+ }
+ }
+
+ protected boolean isSplit() {
+ return getDecorToolbar().isSplit();
+ }
+
+ protected boolean isOverflowPopupNeeded() {
+ return mCallback.isOverflowPopupNeeded();
+ }
+
+ /**
+ * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
+ * adds them to the action bar.
+ */
+ protected void inflateMenus() {
+ MenuInflater inflater = new MenuInflater(getActionMenuContext());
+ MenuBuilder menuBuilder = getMenuBuilder();
+ for (String name : mCallback.getMenuIdNames()) {
+ int id;
+ if (name.startsWith(ANDROID_NS_NAME_PREFIX)) {
+ // Framework menu.
+ name = name.substring(ANDROID_NS_NAME_PREFIX.length());
+ id = mContext.getFrameworkResourceValue(MENU, name, -1);
+ } else {
+ // Project menu.
+ id = mContext.getProjectResourceValue(MENU, name, -1);
+ }
+ if (id > -1) {
+ inflater.inflate(id, menuBuilder);
+ }
+ }
+ }
+
+ /**
+ * The context used for the ActionBar and the menus in the ActionBarView.
+ */
+ @NonNull
+ protected Context getActionMenuContext() {
+ return mActionBar.getThemedContext();
+ }
+
+ /**
+ * The context used to inflate the popup menu.
+ */
+ @NonNull
+ abstract Context getPopupContext();
+
+ /**
+ * The Menu in which to inflate the user's menus.
+ */
+ @NonNull
+ abstract MenuBuilder getMenuBuilder();
+
+ @Nullable
+ abstract ActionMenuPresenter getActionMenuPresenter();
+
+ /**
+ * Framework's wrapper over two ActionBar implementations.
+ */
+ @NonNull
+ abstract DecorToolbar getDecorToolbar();
+
+ // ---- The implementations ----
+
+ /**
+ * Material theme uses {@link Toolbar} as the action bar. This wrapper provides access to
+ * Toolbar using a common API.
+ */
+ private static class ToolbarWrapper extends CustomActionBarWrapper {
+
+ @NonNull
+ private final Toolbar mToolbar; // This is the view.
+
+ ToolbarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+ @NonNull Toolbar toolbar) {
+ super(context, params, new ToolbarActionBar(toolbar, "", new WindowCallback())
+ );
+ mToolbar = toolbar;
+ }
+
+ @Override
+ protected void inflateMenus() {
+ super.inflateMenus();
+ // Inflating the menus doesn't initialize the ActionMenuPresenter. Setting a fake menu
+ // and then setting it back does the trick.
+ MenuBuilder menu = getMenuBuilder();
+ DecorToolbar decorToolbar = getDecorToolbar();
+ decorToolbar.setMenu(new MenuBuilder(getActionMenuContext()), null);
+ decorToolbar.setMenu(menu, null);
+ }
+
+ @NonNull
+ @Override
+ Context getPopupContext() {
+ return Toolbar_Accessor.getPopupContext(mToolbar);
+ }
+
+ @NonNull
+ @Override
+ MenuBuilder getMenuBuilder() {
+ return (MenuBuilder) mToolbar.getMenu();
+ }
+
+ @Nullable
+ @Override
+ ActionMenuPresenter getActionMenuPresenter() {
+ return Toolbar_Accessor.getActionMenuPresenter(mToolbar);
+ }
+
+ @NonNull
+ @Override
+ DecorToolbar getDecorToolbar() {
+ return mToolbar.getWrapper();
+ }
+ }
+
+ /**
+ * Holo theme uses {@link WindowDecorActionBar} as the action bar. This wrapper provides
+ * access to it using a common API.
+ */
+ private static class WindowActionBarWrapper extends CustomActionBarWrapper{
+
+ @NonNull
+ private final WindowDecorActionBar mActionBar;
+ private final ActionBarView mActionBarView;
+ private MenuBuilder mMenuBuilder;
+
+ public WindowActionBarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+ @NonNull View decorContentRoot, @NonNull ActionBarView actionBarView) {
+ super(context, params, new WindowDecorActionBar(decorContentRoot)
+ );
+ mActionBarView = actionBarView;
+ mActionBar = ((WindowDecorActionBar) super.mActionBar);
+ }
+
+ @Override
+ protected void setupActionBar() {
+ super.setupActionBar();
+
+ // Set the navigation mode.
+ int navMode = mCallback.getNavigationMode();
+ mActionBar.setNavigationMode(navMode);
+ //noinspection deprecation
+ if (navMode == ActionBar.NAVIGATION_MODE_TABS) {
+ setupTabs(3);
+ }
+
+ String icon = mParams.getAppIcon();
+ // If the action bar style doesn't specify an icon, set the icon obtained from the
+ // session params.
+ if (!mActionBar.hasIcon() && icon != null) {
+ Drawable iconDrawable = getDrawable(icon, false);
+ if (iconDrawable != null) {
+ mActionBar.setIcon(iconDrawable);
+ }
+ }
+
+ // Set action bar to be split, if needed.
+ ViewGroup splitView = (ViewGroup) mActionBarView.findViewById(R.id.split_action_bar);
+ if (splitView != null) {
+ mActionBarView.setSplitView(splitView);
+ Resources res = mContext.getResources();
+ boolean split = res.getBoolean(R.bool.split_action_bar_is_narrow)
+ && mCallback.getSplitActionBarWhenNarrow();
+ mActionBarView.setSplitToolbar(split);
+ }
+ }
+
+ @Override
+ protected void inflateMenus() {
+ super.inflateMenus();
+ // The super implementation doesn't set the menu on the view. Set it here.
+ mActionBarView.setMenu(getMenuBuilder(), null);
+ }
+
+ @NonNull
+ @Override
+ Context getPopupContext() {
+ return getActionMenuContext();
+ }
+
+ @NonNull
+ @Override
+ MenuBuilder getMenuBuilder() {
+ if (mMenuBuilder == null) {
+ mMenuBuilder = new MenuBuilder(getActionMenuContext());
+ }
+ return mMenuBuilder;
+ }
+
+ @Nullable
+ @Override
+ ActionMenuPresenter getActionMenuPresenter() {
+ return ActionBarAccessor.getActionMenuPresenter(mActionBarView);
+ }
+
+ @NonNull
+ @Override
+ ActionBarView getDecorToolbar() {
+ return mActionBarView;
+ }
+
+ // TODO: Use an adapter, like List View to set up tabs.
+ @SuppressWarnings("deprecation") // For Tab
+ private void setupTabs(int num) {
+ for (int i = 1; i <= num; i++) {
+ Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
+ @Override
+ public void onTabUnselected(Tab t, FragmentTransaction ft) {
+ // pass
+ }
+ @Override
+ public void onTabSelected(Tab t, FragmentTransaction ft) {
+ // pass
+ }
+ @Override
+ public void onTabReselected(Tab t, FragmentTransaction ft) {
+ // pass
+ }
+ });
+ mActionBar.addTab(tab);
+ }
+ }
+
+ @Nullable
+ private Drawable getDrawable(@NonNull String name, boolean isFramework) {
+ RenderResources res = mContext.getRenderResources();
+ ResourceValue value = res.findResValue(name, isFramework);
+ value = res.resolveResValue(value);
+ if (value != null) {
+ return ResourceHelper.getDrawable(value, mContext);
+ }
+ return null;
+ }
+
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index b8dce70..a2eed9a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -353,8 +353,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
// if the theme says no title/action bar, then the size will be 0
if (mActionBarSize > 0) {
- ActionBarLayout actionBar = createActionBar(context, params);
- backgroundLayout.addView(actionBar);
+ ActionBarLayout actionBar = createActionBar(context, params, backgroundLayout);
actionBar.createMenuPopup();
mContentRoot = actionBar.getContentRoot();
} else if (mTitleBarSize > 0) {
@@ -1624,11 +1623,9 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
/**
* Creates the action bar. Also queries the project callback for missing information.
*/
- private ActionBarLayout createActionBar(BridgeContext context, SessionParams params) {
- ActionBarLayout actionBar = new ActionBarLayout(context, params);
- actionBar.setLayoutParams(new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- return actionBar;
+ private ActionBarLayout createActionBar(BridgeContext context, SessionParams params,
+ ViewGroup parentView) {
+ return new ActionBarLayout(context, params, parentView);
}
public BufferedImage getImage() {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java
index a1fae95..979aa33 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java
@@ -16,6 +16,7 @@
package com.android.layoutlib.bridge.util;
+import com.android.annotations.NonNull;
import com.android.resources.ResourceType;
import com.android.util.Pair;
@@ -48,6 +49,7 @@ public class DynamicIdMap {
* @param name the name of the resource
* @return an integer.
*/
+ @NonNull
public Integer getId(ResourceType type, String name) {
return getId(Pair.of(type, name));
}
@@ -59,10 +61,11 @@ public class DynamicIdMap {
* @param resource the type/name of the resource
* @return an integer.
*/
+ @NonNull
public Integer getId(Pair<ResourceType, String> resource) {
Integer value = mDynamicIds.get(resource);
if (value == null) {
- value = Integer.valueOf(++mDynamicSeed);
+ value = ++mDynamicSeed;
mDynamicIds.put(resource, value);
mRevDynamicIds.put(value, resource);
}
diff --git a/tools/split-select/Abi.cpp b/tools/split-select/Abi.cpp
index 20654b6..180dd8f 100644
--- a/tools/split-select/Abi.cpp
+++ b/tools/split-select/Abi.cpp
@@ -16,42 +16,58 @@
#include "Abi.h"
+using namespace android;
+
namespace split {
namespace abi {
-static const std::vector<Variant> sNoneVariants = {};
-static const std::vector<Variant> sArmVariants =
- {Variant::armeabi, Variant::armeabi_v7a, Variant::arm64_v8a};
-static const std::vector<Variant> sIntelVariants = {Variant::x86, Variant::x86_64};
-static const std::vector<Variant> sMipsVariants = {Variant::mips, Variant::mips64};
+static Vector<Variant> buildVariants(Variant v1, Variant v2) {
+ Vector<Variant> v;
+ v.add(v1);
+ v.add(v2);
+ return v;
+}
+
+static Vector<Variant> buildVariants(Variant v1, Variant v2, Variant v3) {
+ Vector<Variant> v;
+ v.add(v1);
+ v.add(v2);
+ v.add(v3);
+ return v;
+}
+
+static const Vector<Variant> sNoneVariants;
+static const Vector<Variant> sArmVariants = buildVariants(Variant_armeabi, Variant_armeabi_v7a, Variant_arm64_v8a);
+static const Vector<Variant> sIntelVariants = buildVariants(Variant_x86, Variant_x86_64);
+static const Vector<Variant> sMipsVariants = buildVariants(Variant_mips, Variant_mips64);
Family getFamily(Variant variant) {
switch (variant) {
- case Variant::none:
- return Family::none;
- case Variant::armeabi:
- case Variant::armeabi_v7a:
- case Variant::arm64_v8a:
- return Family::arm;
- case Variant::x86:
- case Variant::x86_64:
- return Family::intel;
- case Variant::mips:
- case Variant::mips64:
- return Family::mips;
+ case Variant_none:
+ return Family_none;
+ case Variant_armeabi:
+ case Variant_armeabi_v7a:
+ case Variant_arm64_v8a:
+ return Family_arm;
+ case Variant_x86:
+ case Variant_x86_64:
+ return Family_intel;
+ case Variant_mips:
+ case Variant_mips64:
+ return Family_mips;
}
- return Family::none;
+ return Family_none;
}
-const std::vector<Variant>& getVariants(Family family) {
+const Vector<Variant>& getVariants(Family family) {
switch (family) {
- case Family::none:
+ case Family_none:
return sNoneVariants;
- case Family::arm:
+ case Family_arm:
return sArmVariants;
- case Family::intel:
+ case Family_intel:
return sIntelVariants;
- case Family::mips:
+ case Family_mips:
return sMipsVariants;
}
return sNoneVariants;
@@ -59,21 +75,21 @@ const std::vector<Variant>& getVariants(Family family) {
const char* toString(Variant variant) {
switch (variant) {
- case Variant::none:
+ case Variant_none:
return "";
- case Variant::armeabi:
+ case Variant_armeabi:
return "armeabi";
- case Variant::armeabi_v7a:
+ case Variant_armeabi_v7a:
return "armeabi-v7a";
- case Variant::arm64_v8a:
+ case Variant_arm64_v8a:
return "arm64-v8a";
- case Variant::x86:
+ case Variant_x86:
return "x86";
- case Variant::x86_64:
+ case Variant_x86_64:
return "x86_64";
- case Variant::mips:
+ case Variant_mips:
return "mips";
- case Variant::mips64:
+ case Variant_mips64:
return "mips64";
}
return "";
diff --git a/tools/split-select/Abi.h b/tools/split-select/Abi.h
index 3e00eba..85b4d62 100644
--- a/tools/split-select/Abi.h
+++ b/tools/split-select/Abi.h
@@ -17,31 +17,31 @@
#ifndef H_ANDROID_SPLIT_ABI
#define H_ANDROID_SPLIT_ABI
-#include <vector>
+#include <utils/Vector.h>
namespace split {
namespace abi {
-enum class Variant {
- none = 0,
- armeabi,
- armeabi_v7a,
- arm64_v8a,
- x86,
- x86_64,
- mips,
- mips64,
+enum Variant {
+ Variant_none = 0,
+ Variant_armeabi,
+ Variant_armeabi_v7a,
+ Variant_arm64_v8a,
+ Variant_x86,
+ Variant_x86_64,
+ Variant_mips,
+ Variant_mips64,
};
-enum class Family {
- none,
- arm,
- intel,
- mips,
+enum Family {
+ Family_none,
+ Family_arm,
+ Family_intel,
+ Family_mips,
};
Family getFamily(Variant variant);
-const std::vector<Variant>& getVariants(Family family);
+const android::Vector<Variant>& getVariants(Family family);
const char* toString(Variant variant);
} // namespace abi
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
index d0b7287..dc48ea8 100644
--- a/tools/split-select/Android.mk
+++ b/tools/split-select/Android.mk
@@ -17,10 +17,6 @@
# This tool is prebuilt if we're doing an app-only build.
ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
-# TODO(adamlesinski): Enable OS X builds when I figure out how
-# to build with clang and libc++
-ifneq ($(HOST_OS),darwin)
-
# ==========================================================
# Setup some common variables for the different build
# targets here.
@@ -55,7 +51,7 @@ hostStaticLibs := \
libexpat \
libziparchive-host
-cFlags := -std=c++11 -Wall -Werror
+cFlags := -Wall -Werror
ifeq ($(HOST_OS),linux)
hostLdLibs += -lrt -ldl -lpthread
@@ -115,5 +111,4 @@ LOCAL_CFLAGS += $(cFlags)
include $(BUILD_HOST_EXECUTABLE)
-endif # Not OS X
endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/split-select/Grouper.cpp b/tools/split-select/Grouper.cpp
index 15edf89..22685cd 100644
--- a/tools/split-select/Grouper.cpp
+++ b/tools/split-select/Grouper.cpp
@@ -16,25 +16,17 @@
#include "Grouper.h"
+#include "aapt/AaptUtil.h"
#include "SplitDescription.h"
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
using namespace android;
+using AaptUtil::appendValue;
namespace split {
-template <typename Key, typename Value>
-static void addToVector(KeyedVector<Key, SortedVector<Value> >& group,
- const Key& key, const Value& value) {
- ssize_t idx = group.indexOfKey(key);
- if (idx < 0) {
- idx = group.add(key, SortedVector<Value>());
- }
- group.editValueAt(idx).add(value);
-}
-
Vector<SortedVector<SplitDescription> >
groupByMutualExclusivity(const Vector<SplitDescription>& splits) {
Vector<SortedVector<SplitDescription> > groups;
@@ -43,20 +35,22 @@ groupByMutualExclusivity(const Vector<SplitDescription>& splits) {
KeyedVector<SplitDescription, SortedVector<SplitDescription> > densityGroups;
KeyedVector<SplitDescription, SortedVector<SplitDescription> > abiGroups;
KeyedVector<SplitDescription, SortedVector<SplitDescription> > localeGroups;
- for (const SplitDescription& split : splits) {
+ const size_t splitCount = splits.size();
+ for (size_t i = 0; i < splitCount; i++) {
+ const SplitDescription& split = splits[i];
if (split.config.density != 0) {
SplitDescription key(split);
key.config.density = 0;
key.config.sdkVersion = 0; // Ignore density so we can support anydpi.
- addToVector(densityGroups, key, split);
- } else if (split.abi != abi::Variant::none) {
+ appendValue(densityGroups, key, split);
+ } else if (split.abi != abi::Variant_none) {
SplitDescription key(split);
- key.abi = abi::Variant::none;
- addToVector(abiGroups, key, split);
+ key.abi = abi::Variant_none;
+ appendValue(abiGroups, key, split);
} else if (split.config.locale != 0) {
SplitDescription key(split);
key.config.clearLocale();
- addToVector(localeGroups, key, split);
+ appendValue(localeGroups, key, split);
} else {
groups.add();
groups.editTop().add(split);
diff --git a/tools/split-select/Grouper_test.cpp b/tools/split-select/Grouper_test.cpp
index 4d146cd..a5f9c5a 100644
--- a/tools/split-select/Grouper_test.cpp
+++ b/tools/split-select/Grouper_test.cpp
@@ -19,7 +19,6 @@
#include "SplitDescription.h"
#include <gtest/gtest.h>
-#include <initializer_list>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -55,7 +54,11 @@ protected:
}
void addSplit(Vector<SplitDescription>& splits, const char* str);
- void expectHasGroupWithSplits(std::initializer_list<const char*> l);
+ void expectHasGroupWithSplits(const char* a);
+ void expectHasGroupWithSplits(const char* a, const char* b);
+ void expectHasGroupWithSplits(const char* a, const char* b, const char* c);
+ void expectHasGroupWithSplits(const char* a, const char* b, const char* c, const char* d);
+ void expectHasGroupWithSplits(const Vector<const char*>& expectedStrs);
Vector<SortedVector<SplitDescription> > mGroups;
};
@@ -65,39 +68,70 @@ TEST_F(GrouperTest, shouldHaveCorrectNumberOfGroups) {
}
TEST_F(GrouperTest, shouldGroupDensities) {
- expectHasGroupWithSplits({"en-rUS-sw300dp-hdpi", "en-rUS-sw300dp-xhdpi"});
- expectHasGroupWithSplits({"en-rUS-sw600dp-hdpi", "en-rUS-sw600dp-xhdpi"});
- expectHasGroupWithSplits({"fr-rFR-sw600dp-hdpi", "fr-rFR-sw600dp-xhdpi"});
- expectHasGroupWithSplits({"hdpi", "xhdpi", "xxhdpi", "anydpi"});
+ expectHasGroupWithSplits("en-rUS-sw300dp-hdpi", "en-rUS-sw300dp-xhdpi");
+ expectHasGroupWithSplits("en-rUS-sw600dp-hdpi", "en-rUS-sw600dp-xhdpi");
+ expectHasGroupWithSplits("fr-rFR-sw600dp-hdpi", "fr-rFR-sw600dp-xhdpi");
+ expectHasGroupWithSplits("hdpi", "xhdpi", "xxhdpi", "anydpi");
}
TEST_F(GrouperTest, shouldGroupAbi) {
- expectHasGroupWithSplits({":armeabi", ":x86"});
+ expectHasGroupWithSplits(":armeabi", ":x86");
}
TEST_F(GrouperTest, shouldGroupLocale) {
- expectHasGroupWithSplits({"pl-rPL", "de-rDE"});
+ expectHasGroupWithSplits("pl-rPL", "de-rDE");
}
TEST_F(GrouperTest, shouldGroupEachSplitIntoItsOwnGroup) {
- expectHasGroupWithSplits({"large"});
- expectHasGroupWithSplits({"xlarge"});
- expectHasGroupWithSplits({"v7"});
- expectHasGroupWithSplits({"v8"});
- expectHasGroupWithSplits({"sw600dp"});
- expectHasGroupWithSplits({"sw300dp"});
+ expectHasGroupWithSplits("large");
+ expectHasGroupWithSplits("xlarge");
+ expectHasGroupWithSplits("v7");
+ expectHasGroupWithSplits("v8");
+ expectHasGroupWithSplits("sw600dp");
+ expectHasGroupWithSplits("sw300dp");
}
//
// Helper methods
//
-void GrouperTest::expectHasGroupWithSplits(std::initializer_list<const char*> l) {
+void GrouperTest::expectHasGroupWithSplits(const char* a) {
+ Vector<const char*> expected;
+ expected.add(a);
+ expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const char* a, const char* b) {
+ Vector<const char*> expected;
+ expected.add(a);
+ expected.add(b);
+ expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const char* a, const char* b, const char* c) {
+ Vector<const char*> expected;
+ expected.add(a);
+ expected.add(b);
+ expected.add(c);
+ expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const char* a, const char* b, const char* c, const char* d) {
+ Vector<const char*> expected;
+ expected.add(a);
+ expected.add(b);
+ expected.add(c);
+ expected.add(d);
+ expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const Vector<const char*>& expectedStrs) {
Vector<SplitDescription> splits;
- for (const char* str : l) {
+ const size_t expectedStrCount = expectedStrs.size();
+ for (size_t i = 0; i < expectedStrCount; i++) {
splits.add();
- if (!SplitDescription::parse(String8(str), &splits.editTop())) {
- ADD_FAILURE() << "Failed to parse SplitDescription " << str;
+ if (!SplitDescription::parse(String8(expectedStrs[i]), &splits.editTop())) {
+ ADD_FAILURE() << "Failed to parse SplitDescription " << expectedStrs[i];
return;
}
}
diff --git a/tools/split-select/Main.cpp b/tools/split-select/Main.cpp
index d6251c3..434494e 100644
--- a/tools/split-select/Main.cpp
+++ b/tools/split-select/Main.cpp
@@ -63,7 +63,7 @@ static void help() {
class SplitSelector {
public:
- SplitSelector() = default;
+ SplitSelector();
SplitSelector(const Vector<SplitDescription>& splits);
Vector<SplitDescription> getBestSplits(const SplitDescription& target) const;
@@ -75,6 +75,9 @@ private:
Vector<SortedVector<SplitDescription> > mGroups;
};
+SplitSelector::SplitSelector() {
+}
+
SplitSelector::SplitSelector(const Vector<SplitDescription>& splits)
: mGroups(groupByMutualExclusivity(splits)) {
}
diff --git a/tools/split-select/RuleGenerator.cpp b/tools/split-select/RuleGenerator.cpp
index 669ae78..b8f3bcb 100644
--- a/tools/split-select/RuleGenerator.cpp
+++ b/tools/split-select/RuleGenerator.cpp
@@ -65,12 +65,12 @@ sp<Rule> RuleGenerator::generateDensity(const Vector<int>& allDensities, size_t
sp<Rule> RuleGenerator::generateAbi(const Vector<abi::Variant>& splitAbis, size_t index) {
const abi::Variant thisAbi = splitAbis[index];
- const std::vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi));
+ const Vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi));
- std::vector<abi::Variant>::const_iterator start =
+ Vector<abi::Variant>::const_iterator start =
std::find(familyVariants.begin(), familyVariants.end(), thisAbi);
- std::vector<abi::Variant>::const_iterator end = familyVariants.end();
+ Vector<abi::Variant>::const_iterator end = familyVariants.end();
if (index + 1 < splitAbis.size()) {
end = std::find(start, familyVariants.end(), splitAbis[index + 1]);
}
@@ -127,7 +127,7 @@ sp<Rule> RuleGenerator::generate(const SortedVector<SplitDescription>& group, si
rootRule->subrules.add(generateDensity(allDensities, densityIndex));
}
- if (group[index].abi != abi::Variant::none) {
+ if (group[index].abi != abi::Variant_none) {
size_t abiIndex = 0;
Vector<abi::Variant> allVariants;
allVariants.add(group[index].abi);
diff --git a/tools/split-select/RuleGenerator_test.cpp b/tools/split-select/RuleGenerator_test.cpp
index 60baabe..ee387be 100644
--- a/tools/split-select/RuleGenerator_test.cpp
+++ b/tools/split-select/RuleGenerator_test.cpp
@@ -25,19 +25,19 @@ using namespace android;
namespace split {
static void expectDensityRule(const Vector<int>& densities, int density, int greaterThan, int lessThan);
-static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant,
- std::initializer_list<const char*> matches);
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a);
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a, const char* b);
TEST(RuleGeneratorTest, testAbiRules) {
Vector<abi::Variant> abis;
- abis.add(abi::Variant::armeabi);
- abis.add(abi::Variant::armeabi_v7a);
- abis.add(abi::Variant::x86);
+ abis.add(abi::Variant_armeabi);
+ abis.add(abi::Variant_armeabi_v7a);
+ abis.add(abi::Variant_x86);
std::sort(abis.begin(), abis.end());
- expectAbiRule(abis, abi::Variant::armeabi, {"armeabi"});
- expectAbiRule(abis, abi::Variant::armeabi_v7a, {"armeabi-v7a", "arm64-v8a"});
- expectAbiRule(abis, abi::Variant::x86, {"x86", "x86_64"});
+ expectAbiRule(abis, abi::Variant_armeabi, "armeabi");
+ expectAbiRule(abis, abi::Variant_armeabi_v7a, "armeabi-v7a", "arm64-v8a");
+ expectAbiRule(abis, abi::Variant_x86, "x86", "x86_64");
}
TEST(RuleGeneratorTest, testDensityRules) {
@@ -126,8 +126,7 @@ static void expectDensityRule(const Vector<int>& densities, int density, int gre
}
}
-static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant,
- std::initializer_list<const char*> matches) {
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const Vector<const char*>& matches) {
const abi::Variant* iter = std::find(abis.begin(), abis.end(), variant);
if (abis.end() == iter) {
ADD_FAILURE() << abi::toString(variant) << " was not in the abi list.";
@@ -143,7 +142,9 @@ static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant
EXPECT_EQ(matches.size(), rule->stringArgs.size())
<< " for " << abi::toString(variant) << " rule";
- for (const char* match : matches) {
+ const size_t matchCount = matches.size();
+ for (size_t i = 0; i < matchCount; i++) {
+ const char* match = matches[i];
if (rule->stringArgs.end() ==
std::find(rule->stringArgs.begin(), rule->stringArgs.end(), String8(match))) {
ADD_FAILURE() << "Rule for abi " << abi::toString(variant)
@@ -152,4 +153,17 @@ static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant
}
}
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a) {
+ Vector<const char*> matches;
+ matches.add(a);
+ expectAbiRule(abis, variant, matches);
+}
+
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a, const char* b) {
+ Vector<const char*> matches;
+ matches.add(a);
+ matches.add(b);
+ expectAbiRule(abis, variant, matches);
+}
+
} // namespace split
diff --git a/tools/split-select/SplitDescription.cpp b/tools/split-select/SplitDescription.cpp
index 8037ef0..99bc23d 100644
--- a/tools/split-select/SplitDescription.cpp
+++ b/tools/split-select/SplitDescription.cpp
@@ -27,7 +27,7 @@ using namespace android;
namespace split {
SplitDescription::SplitDescription()
-: abi(abi::Variant::none) {
+: abi(abi::Variant_none) {
}
int SplitDescription::compare(const SplitDescription& rhs) const {
@@ -38,11 +38,11 @@ int SplitDescription::compare(const SplitDescription& rhs) const {
}
bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const {
- if (abi != abi::Variant::none || o.abi != abi::Variant::none) {
+ if (abi != abi::Variant_none || o.abi != abi::Variant_none) {
abi::Family family = abi::getFamily(abi);
abi::Family oFamily = abi::getFamily(o.abi);
if (family != oFamily) {
- return family != abi::Family::none;
+ return family != abi::Family_none;
}
if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) {
@@ -53,7 +53,7 @@ bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescri
}
bool SplitDescription::match(const SplitDescription& o) const {
- if (abi != abi::Variant::none) {
+ if (abi != abi::Variant_none) {
abi::Family family = abi::getFamily(abi);
abi::Family oFamily = abi::getFamily(o.abi);
if (family != oFamily) {
@@ -69,7 +69,7 @@ bool SplitDescription::match(const SplitDescription& o) const {
String8 SplitDescription::toString() const {
String8 extension;
- if (abi != abi::Variant::none) {
+ if (abi != abi::Variant_none) {
if (extension.isEmpty()) {
extension.append(":");
} else {
@@ -85,40 +85,40 @@ String8 SplitDescription::toString() const {
ssize_t parseAbi(const Vector<String8>& parts, const ssize_t index,
SplitDescription* outSplit) {
const ssize_t N = parts.size();
- abi::Variant abi = abi::Variant::none;
+ abi::Variant abi = abi::Variant_none;
ssize_t endIndex = index;
if (parts[endIndex] == "arm64") {
endIndex++;
if (endIndex < N) {
if (parts[endIndex] == "v8a") {
endIndex++;
- abi = abi::Variant::arm64_v8a;
+ abi = abi::Variant_arm64_v8a;
}
}
} else if (parts[endIndex] == "armeabi") {
endIndex++;
- abi = abi::Variant::armeabi;
+ abi = abi::Variant_armeabi;
if (endIndex < N) {
if (parts[endIndex] == "v7a") {
endIndex++;
- abi = abi::Variant::armeabi_v7a;
+ abi = abi::Variant_armeabi_v7a;
}
}
} else if (parts[endIndex] == "x86") {
endIndex++;
- abi = abi::Variant::x86;
+ abi = abi::Variant_x86;
} else if (parts[endIndex] == "x86_64") {
endIndex++;
- abi = abi::Variant::x86_64;
+ abi = abi::Variant_x86_64;
} else if (parts[endIndex] == "mips") {
endIndex++;
- abi = abi::Variant::mips;
+ abi = abi::Variant_mips;
} else if (parts[endIndex] == "mips64") {
endIndex++;
- abi = abi::Variant::mips64;
+ abi = abi::Variant_mips64;
}
- if (abi == abi::Variant::none && endIndex != index) {
+ if (abi == abi::Variant_none && endIndex != index) {
return -1;
}
diff --git a/tools/split-select/SplitDescription.h b/tools/split-select/SplitDescription.h
index 5fcafc8..b13c9ee 100644
--- a/tools/split-select/SplitDescription.h
+++ b/tools/split-select/SplitDescription.h
@@ -27,7 +27,6 @@ namespace split {
struct SplitDescription {
SplitDescription();
- SplitDescription(const SplitDescription&) = default;
ConfigDescription config;
abi::Variant abi;
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 5bf3470..75198e5 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -286,7 +286,7 @@ public class WifiInfo implements Parcelable {
* Returns the service set identifier (SSID) of the current 802.11 network.
* If the SSID can be decoded as UTF-8, it will be returned surrounded by double
* quotation marks. Otherwise, it is returned as a string of hex digits. The
- * SSID may be {@code null} if there is no network currently connected.
+ * SSID may be &lt;unknown ssid&gt; if there is no network currently connected.
* @return the SSID
*/
public String getSSID() {