summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt176
-rw-r--r--core/java/android/app/ActionBar.java219
-rw-r--r--core/java/android/app/Activity.java136
-rw-r--r--core/java/android/app/ActivityOptions.java110
-rw-r--r--core/java/android/app/Dialog.java6
-rw-r--r--core/java/android/app/UiModeManager.java8
-rw-r--r--core/java/android/content/Context.java6
-rw-r--r--core/java/android/content/Intent.java31
-rw-r--r--core/java/android/content/res/Configuration.java10
-rw-r--r--core/java/android/content/res/Resources.java9
-rw-r--r--core/java/android/os/IPowerManager.aidl3
-rw-r--r--core/java/android/text/StaticLayout.java2
-rw-r--r--core/java/android/transition/CircularPropagation.java103
-rw-r--r--core/java/android/transition/Explode.java228
-rw-r--r--core/java/android/transition/Fade.java258
-rw-r--r--core/java/android/transition/MatrixClippedDrawable.java300
-rw-r--r--core/java/android/transition/MoveImage.java326
-rw-r--r--core/java/android/transition/SidePropagation.java165
-rw-r--r--core/java/android/transition/Slide.java243
-rw-r--r--core/java/android/transition/Transition.java162
-rw-r--r--core/java/android/transition/TransitionInflater.java18
-rw-r--r--core/java/android/transition/TransitionPropagation.java88
-rw-r--r--core/java/android/transition/TransitionSet.java29
-rw-r--r--core/java/android/transition/Visibility.java200
-rw-r--r--core/java/android/transition/VisibilityPropagation.java112
-rw-r--r--core/java/android/view/Window.java55
-rw-r--r--core/java/android/widget/ActionMenuPresenter.java10
-rw-r--r--core/java/android/widget/ActionMenuView.java54
-rw-r--r--core/java/android/widget/Toolbar.java1048
-rw-r--r--core/java/com/android/internal/app/ToolbarActionBar.java452
-rw-r--r--core/java/com/android/internal/app/WindowDecorActionBar.java (renamed from core/java/com/android/internal/app/ActionBarImpl.java)21
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl1
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuItemView.java5
-rw-r--r--core/java/com/android/internal/widget/ActionBarContainer.java7
-rw-r--r--core/java/com/android/internal/widget/ActionBarOverlayLayout.java6
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java2
-rw-r--r--core/java/com/android/internal/widget/AutoScrollHelper.java4
-rw-r--r--core/jni/android/graphics/Bitmap.cpp2
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp2
-rw-r--r--core/jni/android/graphics/BitmapRegionDecoder.cpp2
-rw-r--r--core/jni/android/graphics/Canvas.cpp44
-rw-r--r--core/jni/android/graphics/ColorFilter.cpp2
-rw-r--r--core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp8
-rw-r--r--core/jni/android/graphics/MaskFilter.cpp2
-rw-r--r--core/jni/android/graphics/Matrix.cpp102
-rw-r--r--core/jni/android/graphics/PathEffect.cpp12
-rw-r--r--core/jni/android/graphics/Xfermode.cpp4
-rw-r--r--core/jni/android_view_RenderNode.cpp3
-rw-r--r--core/res/res/drawable-hdpi/ab_bottom_solid_qntm_alpha.9.pngbin135 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.pngbin138 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.pngbin133 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.pngbin141 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.pngbin140 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.pngbin124 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_alarm_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_alarm.png)bin1252 -> 1252 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_alarm_mute_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_alarm_mute.png)bin1376 -> 1376 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_bt_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_bt.png)bin1009 -> 1009 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_bt_mute_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_bt_mute.png)bin1214 -> 1214 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_notification_am_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_notification_am.png)bin1015 -> 1015 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_notification_mute_am_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_notification_mute_am.png)bin1249 -> 1249 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_phone_am_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_phone_am.png)bin943 -> 943 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_ring_notif_am_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_ring_notif_am.png)bin1196 -> 1196 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am.png)bin1398 -> 1398 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am.png)bin1309 -> 1309 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_vol_am_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_vol_am.png)bin1226 -> 1226 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_audio_vol_mute_am_alpha.png (renamed from core/res/res/drawable-hdpi/ic_audio_vol_mute_am.png)bin1398 -> 1398 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_airplane_mode_alpha.png (renamed from core/res/res/drawable-hdpi/ic_lock_airplane_mode.png)bin1250 -> 1250 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am_alpha.png (renamed from core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am.png)bin1194 -> 1194 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.pngbin0 -> 170 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_idle_alarm_alpha.png (renamed from core/res/res/drawable-hdpi/ic_lock_idle_alarm.png)bin830 -> 830 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_lock_alpha.png (renamed from core/res/res/drawable-hdpi/ic_lock_lock.png)bin789 -> 789 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_power_off_alpha.png (renamed from core/res/res/drawable-hdpi/ic_lock_power_off.png)bin1304 -> 1304 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_ringer_off_alpha.png (renamed from core/res/res/drawable-hdpi/ic_lock_ringer_off.png)bin1378 -> 1378 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_ringer_on_alpha.png (renamed from core/res/res/drawable-hdpi/ic_lock_ringer_on.png)bin1757 -> 1757 bytes
-rw-r--r--core/res/res/drawable-ldpi/ic_lock_airplane_mode_alpha.png (renamed from core/res/res/drawable-ldpi/ic_lock_airplane_mode.png)bin1057 -> 1057 bytes
-rw-r--r--core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am_alpha.png (renamed from core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am.png)bin1173 -> 1173 bytes
-rw-r--r--core/res/res/drawable-ldpi/ic_lock_idle_alarm_alpha.png (renamed from core/res/res/drawable-ldpi/ic_lock_idle_alarm.png)bin824 -> 824 bytes
-rw-r--r--core/res/res/drawable-ldpi/ic_lock_lock_alpha.png (renamed from core/res/res/drawable-ldpi/ic_lock_lock.png)bin972 -> 972 bytes
-rw-r--r--core/res/res/drawable-ldpi/ic_lock_power_off_alpha.png (renamed from core/res/res/drawable-ldpi/ic_lock_power_off.png)bin1225 -> 1225 bytes
-rw-r--r--core/res/res/drawable-ldpi/ic_lock_ringer_off_alpha.png (renamed from core/res/res/drawable-ldpi/ic_lock_ringer_off.png)bin782 -> 782 bytes
-rw-r--r--core/res/res/drawable-ldpi/ic_lock_ringer_on_alpha.png (renamed from core/res/res/drawable-ldpi/ic_lock_ringer_on.png)bin857 -> 857 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.pngbin117 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.pngbin120 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.pngbin117 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.pngbin122 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.pngbin121 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.pngbin111 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_alarm_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_alarm.png)bin847 -> 847 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_alarm_mute_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_alarm_mute.png)bin890 -> 890 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_bt_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_bt.png)bin740 -> 740 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_bt_mute_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_bt_mute.png)bin845 -> 845 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_notification_am_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_notification_am.png)bin758 -> 758 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_notification_mute_am_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_notification_mute_am.png)bin870 -> 870 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_phone_am_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_phone_am.png)bin700 -> 700 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_ring_notif_am_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_ring_notif_am.png)bin855 -> 855 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am.png)bin918 -> 918 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am.png)bin905 -> 905 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_vol_am_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_vol_am.png)bin849 -> 849 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_audio_vol_mute_am_alpha.png (renamed from core/res/res/drawable-mdpi/ic_audio_vol_mute_am.png)bin918 -> 918 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_airplane_mode_alpha.png (renamed from core/res/res/drawable-mdpi/ic_lock_airplane_mode.png)bin891 -> 891 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am_alpha.png (renamed from core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am.png)bin862 -> 862 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.pngbin0 -> 147 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_idle_alarm_alpha.png (renamed from core/res/res/drawable-mdpi/ic_lock_idle_alarm.png)bin585 -> 585 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_lock_alpha.png (renamed from core/res/res/drawable-mdpi/ic_lock_lock.png)bin636 -> 636 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_power_off_alpha.png (renamed from core/res/res/drawable-mdpi/ic_lock_power_off.png)bin913 -> 913 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_ringer_off_alpha.png (renamed from core/res/res/drawable-mdpi/ic_lock_ringer_off.png)bin906 -> 906 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_ringer_on_alpha.png (renamed from core/res/res/drawable-mdpi/ic_lock_ringer_on.png)bin977 -> 977 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.pngbin150 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.pngbin145 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.pngbin149 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.pngbin155 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.pngbin150 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.pngbin142 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_alarm_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_alarm.png)bin1729 -> 1729 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_alarm_mute_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_alarm_mute.png)bin1954 -> 1954 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_bt_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_bt.png)bin1281 -> 1281 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_bt_mute_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_bt_mute.png)bin1640 -> 1640 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_notification_am_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_notification_am.png)bin1257 -> 1257 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_notification_mute_am_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_notification_mute_am.png)bin1680 -> 1680 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_phone_am_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_phone_am.png)bin1195 -> 1195 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_ring_notif_am_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_ring_notif_am.png)bin1581 -> 1581 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am.png)bin1949 -> 1949 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am.png)bin1840 -> 1840 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_vol_am_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_vol_am.png)bin1684 -> 1684 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_audio_vol_mute_am_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_audio_vol_mute_am.png)bin1949 -> 1949 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_airplane_mode_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_lock_airplane_mode.png)bin1668 -> 1668 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am.png)bin1573 -> 1573 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.pngbin0 -> 194 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_idle_alarm_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_lock_idle_alarm.png)bin1157 -> 1157 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_lock_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_lock_lock.png)bin954 -> 954 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_power_off_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_lock_power_off.png)bin1754 -> 1754 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_ringer_off_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_lock_ringer_off.png)bin1639 -> 1639 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_ringer_on_alpha.png (renamed from core/res/res/drawable-xhdpi/ic_lock_ringer_on.png)bin2069 -> 2069 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.pngbin233 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.pngbin220 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.pngbin275 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.pngbin218 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.pngbin218 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.pngbin205 -> 0 bytes
-rwxr-xr-xcore/res/res/drawable-xxhdpi/ic_audio_alarm_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_alarm.png)bin1775 -> 1775 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_audio_alarm_mute_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_alarm_mute.png)bin2240 -> 2240 bytes
-rwxr-xr-xcore/res/res/drawable-xxhdpi/ic_audio_bt_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_bt.png)bin1242 -> 1242 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_audio_bt_mute_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_bt_mute.png)bin1642 -> 1642 bytes
-rwxr-xr-xcore/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_notification_am.png)bin1230 -> 1230 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am.png)bin1772 -> 1772 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_audio_phone_am_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_phone_am.png)bin1353 -> 1353 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am.png)bin1641 -> 1641 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am.png)bin2245 -> 2245 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am.png)bin2695 -> 2695 bytes
-rwxr-xr-xcore/res/res/drawable-xxhdpi/ic_audio_vol_am_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_vol_am.png)bin1690 -> 1690 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am.png)bin2245 -> 2245 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_lock_airplane_mode.png)bin2190 -> 2190 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am.png)bin1586 -> 1586 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.pngbin0 -> 327 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_lock_idle_alarm_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_lock_idle_alarm.png)bin2116 -> 2116 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_lock_lock_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_lock_lock.png)bin1565 -> 1565 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_lock_power_off_alpha.png (renamed from core/res/res/drawable-xxhdpi/ic_lock_power_off.png)bin1603 -> 1603 bytes
-rw-r--r--core/res/res/drawable/ab_bottom_transparent_quantum.xml21
-rw-r--r--core/res/res/drawable/ab_stacked_transparent_quantum.xml20
-rw-r--r--core/res/res/drawable/ic_audio_alarm.xml (renamed from core/res/res/drawable/ab_transparent_quantum.xml)2
-rw-r--r--core/res/res/drawable/ic_audio_alarm_mute.xml (renamed from core/res/res/drawable/ab_solid_quantum.xml)5
-rw-r--r--core/res/res/drawable/ic_audio_bt.xml (renamed from core/res/res/drawable/ab_bottom_solid_quantum.xml)5
-rw-r--r--core/res/res/drawable/ic_audio_bt_mute.xml (renamed from core/res/res/drawable/ab_stacked_solid_quantum.xml)5
-rw-r--r--core/res/res/drawable/ic_audio_notification.xml6
-rw-r--r--core/res/res/drawable/ic_audio_notification_mute.xml6
-rw-r--r--core/res/res/drawable/ic_audio_phone.xml6
-rw-r--r--core/res/res/drawable/ic_audio_ring_notif.xml6
-rw-r--r--core/res/res/drawable/ic_audio_ring_notif_mute.xml6
-rw-r--r--core/res/res/drawable/ic_audio_ring_notif_vibrate.xml6
-rw-r--r--core/res/res/drawable/ic_audio_vol.xml6
-rw-r--r--core/res/res/drawable/ic_audio_vol_mute.xml6
-rw-r--r--core/res/res/drawable/ic_lock_airplane_mode.xml19
-rw-r--r--core/res/res/drawable/ic_lock_airplane_mode_off.xml6
-rw-r--r--core/res/res/drawable/ic_lock_bugreport.xml19
-rw-r--r--core/res/res/drawable/ic_lock_idle_alarm.xml19
-rw-r--r--core/res/res/drawable/ic_lock_lock.xml19
-rw-r--r--core/res/res/drawable/ic_lock_power_off.xml19
-rw-r--r--core/res/res/layout/alert_dialog_quantum.xml11
-rw-r--r--core/res/res/layout/dialog_custom_title_quantum.xml13
-rw-r--r--core/res/res/layout/dialog_title_icons_quantum.xml11
-rw-r--r--core/res/res/layout/dialog_title_quantum.xml44
-rw-r--r--core/res/res/layout/screen_action_bar.xml10
-rw-r--r--core/res/res/values/attrs.xml55
-rw-r--r--core/res/res/values/colors_quantum.xml48
-rw-r--r--core/res/res/values/config.xml1
-rw-r--r--core/res/res/values/public.xml4
-rw-r--r--core/res/res/values/styles.xml15
-rw-r--r--core/res/res/values/styles_quantum.xml79
-rw-r--r--core/res/res/values/symbols.xml6
-rw-r--r--core/res/res/values/themes.xml2
-rw-r--r--core/res/res/values/themes_quantum.xml44
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java11
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java33
-rw-r--r--docs/html/guide/topics/resources/providing-resources.jd4
-rw-r--r--docs/html/training/basics/actionbar/styling.jd4
-rw-r--r--docs/html/training/game-controllers/controller-input.jd21
-rw-r--r--docs/html/training/notify-user/display-progress.jd9
-rw-r--r--docs/html/training/notify-user/navigation.jd1
-rw-r--r--graphics/java/android/graphics/Matrix.java134
-rw-r--r--graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java5
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java403
-rw-r--r--include/androidfw/ResourceTypes.h1
-rw-r--r--libs/androidfw/ResourceTypes.cpp3
-rw-r--r--libs/hwui/Caches.cpp16
-rw-r--r--libs/hwui/Caches.h6
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp4
-rw-r--r--libs/hwui/DeferredLayerUpdater.h2
-rw-r--r--libs/hwui/DisplayList.cpp14
-rw-r--r--libs/hwui/DisplayList.h16
-rw-r--r--libs/hwui/DisplayListOp.h2
-rw-r--r--libs/hwui/DisplayListRenderer.cpp2
-rw-r--r--libs/hwui/Layer.cpp11
-rw-r--r--libs/hwui/Layer.h11
-rw-r--r--libs/hwui/OpenGLRenderer.cpp2
-rw-r--r--libs/hwui/RenderNode.cpp35
-rw-r--r--libs/hwui/RenderNode.h4
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp64
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h25
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp7
-rw-r--r--libs/hwui/utils/VirtualLightRefBase.h34
-rw-r--r--libs/input/SpriteController.cpp2
-rw-r--r--libs/input/SpriteController.h2
-rw-r--r--packages/SystemUI/res/values/config.xml5
-rw-r--r--packages/SystemUI/res/values/dimens.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Utilities.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/Task.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java204
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java15
-rw-r--r--policy/src/com/android/internal/policy/impl/GlobalActions.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java472
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java6
-rw-r--r--services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java124
-rw-r--r--services/core/java/com/android/server/EventLogTags.logtags6
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java10
-rwxr-xr-x[-rw-r--r--]services/core/java/com/android/server/am/ActivityRecord.java9
-rw-r--r--services/core/java/com/android/server/notification/NotificationDelegate.java1
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java10
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java7
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java11
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp4
-rw-r--r--services/core/jni/com_android_server_power_PowerManagerService.cpp14
-rw-r--r--tools/aapt/AaptAssets.cpp5
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java45
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java79
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java32
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java5
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java3
260 files changed, 6200 insertions, 1303 deletions
diff --git a/api/current.txt b/api/current.txt
index 852312b200e5..ae4be123da06 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -246,6 +246,7 @@ package android {
field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
field public static final int actionBarTabStyle = 16843507; // 0x10102f3
field public static final int actionBarTabTextStyle = 16843509; // 0x10102f5
+ field public static final int actionBarTheme = 16843836; // 0x101043c
field public static final int actionBarWidgetTheme = 16843671; // 0x1010397
field public static final int actionButtonStyle = 16843480; // 0x10102d8
field public static final int actionDropDownStyle = 16843479; // 0x10102d7
@@ -1020,6 +1021,7 @@ package android {
field public static final int shrinkColumns = 16843082; // 0x101014a
field public static final deprecated int singleLine = 16843101; // 0x101015d
field public static final int singleUser = 16843711; // 0x10103bf
+ field public static final int slideEdge = 16843835; // 0x101043b
field public static final int smallIcon = 16843422; // 0x101029e
field public static final int smallScreens = 16843396; // 0x1010284
field public static final int smoothScrollbar = 16843313; // 0x1010231
@@ -1075,6 +1077,7 @@ package android {
field public static final int strokeOpacity = 16843812; // 0x1010424
field public static final int strokeWidth = 16843813; // 0x1010425
field public static final int subtitle = 16843473; // 0x10102d1
+ field public static final int subtitleTextAppearance = 16843834; // 0x101043a
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
field public static final int subtypeId = 16843713; // 0x10103c1
@@ -1190,6 +1193,7 @@ package android {
field public static final int tintMode = 16843798; // 0x1010416
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
+ field public static final int titleTextAppearance = 16843833; // 0x1010439
field public static final int titleTextStyle = 16843512; // 0x10102f8
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
@@ -3017,30 +3021,30 @@ package android.app {
public abstract class ActionBar {
ctor public ActionBar();
method public abstract void addOnMenuVisibilityListener(android.app.ActionBar.OnMenuVisibilityListener);
- method public abstract void addTab(android.app.ActionBar.Tab);
- method public abstract void addTab(android.app.ActionBar.Tab, boolean);
- method public abstract void addTab(android.app.ActionBar.Tab, int);
- method public abstract void addTab(android.app.ActionBar.Tab, int, boolean);
+ method public abstract deprecated void addTab(android.app.ActionBar.Tab);
+ method public abstract deprecated void addTab(android.app.ActionBar.Tab, boolean);
+ method public abstract deprecated void addTab(android.app.ActionBar.Tab, int);
+ method public abstract deprecated void addTab(android.app.ActionBar.Tab, int, boolean);
method public abstract android.view.View getCustomView();
method public abstract int getDisplayOptions();
method public abstract int getHeight();
- method public abstract int getNavigationItemCount();
- method public abstract int getNavigationMode();
- method public abstract int getSelectedNavigationIndex();
- method public abstract android.app.ActionBar.Tab getSelectedTab();
+ method public abstract deprecated int getNavigationItemCount();
+ method public abstract deprecated int getNavigationMode();
+ method public abstract deprecated int getSelectedNavigationIndex();
+ method public abstract deprecated android.app.ActionBar.Tab getSelectedTab();
method public abstract java.lang.CharSequence getSubtitle();
- method public abstract android.app.ActionBar.Tab getTabAt(int);
- method public abstract int getTabCount();
+ method public abstract deprecated android.app.ActionBar.Tab getTabAt(int);
+ method public abstract deprecated int getTabCount();
method public android.content.Context getThemedContext();
method public abstract java.lang.CharSequence getTitle();
method public abstract void hide();
method public abstract boolean isShowing();
- method public abstract android.app.ActionBar.Tab newTab();
- method public abstract void removeAllTabs();
+ method public abstract deprecated android.app.ActionBar.Tab newTab();
+ method public abstract deprecated void removeAllTabs();
method public abstract void removeOnMenuVisibilityListener(android.app.ActionBar.OnMenuVisibilityListener);
- method public abstract void removeTab(android.app.ActionBar.Tab);
- method public abstract void removeTabAt(int);
- method public abstract void selectTab(android.app.ActionBar.Tab);
+ method public abstract deprecated void removeTab(android.app.ActionBar.Tab);
+ method public abstract deprecated void removeTabAt(int);
+ method public abstract deprecated void selectTab(android.app.ActionBar.Tab);
method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
method public abstract void setCustomView(android.view.View);
method public abstract void setCustomView(android.view.View, android.app.ActionBar.LayoutParams);
@@ -3059,11 +3063,11 @@ package android.app {
method public void setHomeButtonEnabled(boolean);
method public abstract void setIcon(int);
method public abstract void setIcon(android.graphics.drawable.Drawable);
- method public abstract void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar.OnNavigationListener);
+ method public abstract deprecated void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar.OnNavigationListener);
method public abstract void setLogo(int);
method public abstract void setLogo(android.graphics.drawable.Drawable);
- method public abstract void setNavigationMode(int);
- method public abstract void setSelectedNavigationItem(int);
+ method public abstract deprecated void setNavigationMode(int);
+ method public abstract deprecated void setSelectedNavigationItem(int);
method public void setSplitBackgroundDrawable(android.graphics.drawable.Drawable);
method public void setStackedBackgroundDrawable(android.graphics.drawable.Drawable);
method public abstract void setSubtitle(java.lang.CharSequence);
@@ -3076,9 +3080,9 @@ package android.app {
field public static final int DISPLAY_SHOW_HOME = 2; // 0x2
field public static final int DISPLAY_SHOW_TITLE = 8; // 0x8
field public static final int DISPLAY_USE_LOGO = 1; // 0x1
- field public static final int NAVIGATION_MODE_LIST = 1; // 0x1
- field public static final int NAVIGATION_MODE_STANDARD = 0; // 0x0
- field public static final int NAVIGATION_MODE_TABS = 2; // 0x2
+ field public static final deprecated int NAVIGATION_MODE_LIST = 1; // 0x1
+ field public static final deprecated int NAVIGATION_MODE_STANDARD = 0; // 0x0
+ field public static final deprecated int NAVIGATION_MODE_TABS = 2; // 0x2
}
public static class ActionBar.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
@@ -3088,6 +3092,7 @@ package android.app {
ctor public ActionBar.LayoutParams(int);
ctor public ActionBar.LayoutParams(android.app.ActionBar.LayoutParams);
ctor public ActionBar.LayoutParams(android.view.ViewGroup.LayoutParams);
+ ctor public ActionBar.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
field public int gravity;
}
@@ -3095,11 +3100,11 @@ package android.app {
method public abstract void onMenuVisibilityChanged(boolean);
}
- public static abstract interface ActionBar.OnNavigationListener {
+ public static abstract deprecated interface ActionBar.OnNavigationListener {
method public abstract boolean onNavigationItemSelected(int, long);
}
- public static abstract class ActionBar.Tab {
+ public static abstract deprecated class ActionBar.Tab {
ctor public ActionBar.Tab();
method public abstract java.lang.CharSequence getContentDescription();
method public abstract android.view.View getCustomView();
@@ -3121,7 +3126,7 @@ package android.app {
field public static final int INVALID_POSITION = -1; // 0xffffffff
}
- public static abstract interface ActionBar.TabListener {
+ public static abstract deprecated interface ActionBar.TabListener {
method public abstract void onTabReselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
method public abstract void onTabSelected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
method public abstract void onTabUnselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
@@ -3147,6 +3152,7 @@ package android.app {
method public void finishActivityFromChild(android.app.Activity, int);
method public void finishAffinity();
method public void finishFromChild(android.app.Activity);
+ method public void finishWithTransition();
method public android.app.ActionBar getActionBar();
method public final android.app.Application getApplication();
method public android.content.ComponentName getCallingActivity();
@@ -3263,6 +3269,7 @@ package android.app {
method public void reportFullyDrawn();
method public final boolean requestWindowFeature(int);
method public final void runOnUiThread(java.lang.Runnable);
+ method public void setActionBar(android.widget.Toolbar);
method public void setActivityLabelAndIcon(java.lang.CharSequence, android.graphics.Bitmap);
method public void setContentTransitionManager(android.transition.TransitionManager);
method public void setContentView(int);
@@ -6836,6 +6843,8 @@ package android.content {
field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
@@ -6985,6 +6994,7 @@ package android.content {
field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID";
+ field public static final java.lang.String EXTRA_USER = "android.intent.extra.user";
field public static final int FILL_IN_ACTION = 1; // 0x1
field public static final int FILL_IN_CATEGORIES = 4; // 0x4
field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
@@ -8154,6 +8164,7 @@ package android.content.res {
field public static final int UI_MODE_TYPE_NORMAL = 1; // 0x1
field public static final int UI_MODE_TYPE_TELEVISION = 4; // 0x4
field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
+ field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6
field public int densityDpi;
field public float fontScale;
field public int hardKeyboardHidden;
@@ -27398,6 +27409,16 @@ package android.transition {
method public void setResizeClip(boolean);
}
+ public class CircularPropagation extends android.transition.VisibilityPropagation {
+ ctor public CircularPropagation();
+ method public long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues);
+ method public void setPropagationSpeed(float);
+ }
+
+ public class Explode extends android.transition.Visibility {
+ ctor public Explode();
+ }
+
public class Fade extends android.transition.Visibility {
ctor public Fade();
ctor public Fade(int);
@@ -27405,6 +27426,12 @@ package android.transition {
field public static final int OUT = 2; // 0x2
}
+ public class MoveImage extends android.transition.Transition {
+ ctor public MoveImage();
+ method public void captureEndValues(android.transition.TransitionValues);
+ method public void captureStartValues(android.transition.TransitionValues);
+ }
+
public final class Scene {
ctor public Scene(android.view.ViewGroup);
ctor public Scene(android.view.ViewGroup, android.view.View);
@@ -27417,6 +27444,27 @@ package android.transition {
method public void setExitAction(java.lang.Runnable);
}
+ public class SidePropagation extends android.transition.VisibilityPropagation {
+ ctor public SidePropagation();
+ method public long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues);
+ method public void setPropagationSpeed(float);
+ method public void setSide(int);
+ field public static final int BOTTOM = 3; // 0x3
+ field public static final int LEFT = 0; // 0x0
+ field public static final int RIGHT = 2; // 0x2
+ field public static final int TOP = 1; // 0x1
+ }
+
+ public class Slide extends android.transition.Visibility {
+ ctor public Slide();
+ ctor public Slide(int);
+ method public void setSlideEdge(int);
+ field public static final int BOTTOM = 3; // 0x3
+ field public static final int LEFT = 0; // 0x0
+ field public static final int RIGHT = 2; // 0x2
+ field public static final int TOP = 1; // 0x1
+ }
+
public abstract class Transition implements java.lang.Cloneable {
ctor public Transition();
method public android.transition.Transition addListener(android.transition.Transition.TransitionListener);
@@ -27434,8 +27482,11 @@ package android.transition {
method public android.transition.Transition excludeTarget(android.view.View, boolean);
method public android.transition.Transition excludeTarget(java.lang.Class, boolean);
method public long getDuration();
+ method public android.graphics.Rect getEpicenter();
+ method public android.transition.Transition.EpicenterCallback getEpicenterCallback();
method public android.animation.TimeInterpolator getInterpolator();
method public java.lang.String getName();
+ method public android.transition.TransitionPropagation getPropagation();
method public long getStartDelay();
method public java.util.List<java.lang.Integer> getTargetIds();
method public java.util.List<android.view.View> getTargets();
@@ -27445,10 +27496,17 @@ package android.transition {
method public android.transition.Transition removeTarget(int);
method public android.transition.Transition removeTarget(android.view.View);
method public android.transition.Transition setDuration(long);
+ method public void setEpicenterCallback(android.transition.Transition.EpicenterCallback);
method public android.transition.Transition setInterpolator(android.animation.TimeInterpolator);
+ method public void setPropagation(android.transition.TransitionPropagation);
method public android.transition.Transition setStartDelay(long);
}
+ public static abstract class Transition.EpicenterCallback {
+ ctor public Transition.EpicenterCallback();
+ method public abstract android.graphics.Rect getEpicenter(android.transition.Transition);
+ }
+
public static abstract interface Transition.TransitionListener {
method public abstract void onTransitionCancel(android.transition.Transition);
method public abstract void onTransitionEnd(android.transition.Transition);
@@ -27475,6 +27533,13 @@ package android.transition {
method public void transitionTo(android.transition.Scene);
}
+ public abstract class TransitionPropagation {
+ ctor public TransitionPropagation();
+ method public abstract void captureValues(android.transition.TransitionValues);
+ method public abstract java.lang.String[] getPropagationProperties();
+ method public abstract long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues);
+ }
+
public class TransitionSet extends android.transition.Transition {
ctor public TransitionSet();
method public android.transition.TransitionSet addTransition(android.transition.Transition);
@@ -27499,7 +27564,18 @@ package android.transition {
method public void captureStartValues(android.transition.TransitionValues);
method public boolean isVisible(android.transition.TransitionValues);
method public android.animation.Animator onAppear(android.view.ViewGroup, android.transition.TransitionValues, int, android.transition.TransitionValues, int);
+ method public android.animation.Animator onAppear(android.view.ViewGroup, android.view.View, android.transition.TransitionValues, android.transition.TransitionValues);
method public android.animation.Animator onDisappear(android.view.ViewGroup, android.transition.TransitionValues, int, android.transition.TransitionValues, int);
+ method public android.animation.Animator onDisappear(android.view.ViewGroup, android.view.View, android.transition.TransitionValues, android.transition.TransitionValues);
+ }
+
+ public abstract class VisibilityPropagation extends android.transition.TransitionPropagation {
+ ctor public VisibilityPropagation();
+ method public void captureValues(android.transition.TransitionValues);
+ method public java.lang.String[] getPropagationProperties();
+ method public int getViewVisibility(android.transition.TransitionValues);
+ method public int getViewX(android.transition.TransitionValues);
+ method public int getViewY(android.transition.TransitionValues);
}
}
@@ -30452,6 +30528,8 @@ package android.view {
method public boolean requestFeature(int);
method public abstract void restoreHierarchyState(android.os.Bundle);
method public abstract android.os.Bundle saveHierarchyState();
+ method public void setAllowOverlappingEnterTransition(boolean);
+ method public void setAllowOverlappingExitTransition(boolean);
method public void setAttributes(android.view.WindowManager.LayoutParams);
method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
method public void setBackgroundDrawableResource(int);
@@ -30480,7 +30558,6 @@ package android.view {
method public abstract void setTitle(java.lang.CharSequence);
method public abstract deprecated void setTitleColor(int);
method public void setTransitionManager(android.transition.TransitionManager);
- method public void setTriggerEarlyEnterTransition(boolean);
method public void setType(int);
method public void setUiOptions(int);
method public void setUiOptions(int, int);
@@ -32514,6 +32591,7 @@ package android.widget {
method public android.view.Menu getMenu();
method public void onConfigurationChanged(android.content.res.Configuration);
method public void onDetachedFromWindow();
+ method public void setOnMenuItemClickListener(android.widget.ActionMenuView.OnMenuItemClickListener);
}
public static class ActionMenuView.LayoutParams extends android.widget.LinearLayout.LayoutParams {
@@ -32523,6 +32601,10 @@ package android.widget {
ctor public ActionMenuView.LayoutParams(int, int);
}
+ public static abstract interface ActionMenuView.OnMenuItemClickListener {
+ method public abstract boolean onMenuItemClick(android.view.MenuItem);
+ }
+
public abstract interface Adapter {
method public abstract int getCount();
method public abstract java.lang.Object getItem(int);
@@ -34676,6 +34758,50 @@ package android.widget {
method public void setTextOn(java.lang.CharSequence);
}
+ public class Toolbar extends android.view.ViewGroup {
+ ctor public Toolbar(android.content.Context);
+ ctor public Toolbar(android.content.Context, android.util.AttributeSet);
+ ctor public Toolbar(android.content.Context, android.util.AttributeSet, int);
+ ctor public Toolbar(android.content.Context, android.util.AttributeSet, int, int);
+ method public android.graphics.drawable.Drawable getLogo();
+ method public java.lang.CharSequence getLogoDescription();
+ method public android.view.Menu getMenu();
+ method public android.graphics.drawable.Drawable getNavigationIcon();
+ method public java.lang.CharSequence getSubtitle();
+ method public java.lang.CharSequence getTitle();
+ method public void inflateMenu(int);
+ method protected void onLayout(boolean, int, int, int, int);
+ method public void setLogo(int);
+ method public void setLogo(android.graphics.drawable.Drawable);
+ method public void setLogoDescription(int);
+ method public void setLogoDescription(java.lang.CharSequence);
+ method public void setNavigationDescription(int);
+ method public void setNavigationDescription(java.lang.CharSequence);
+ method public void setNavigationIcon(int);
+ method public void setNavigationIcon(android.graphics.drawable.Drawable);
+ method public void setNavigationOnClickListener(android.view.View.OnClickListener);
+ method public void setOnMenuItemClickListener(android.widget.Toolbar.OnMenuItemClickListener);
+ method public void setSubtitle(int);
+ method public void setSubtitle(java.lang.CharSequence);
+ method public void setTitle(int);
+ method public void setTitle(java.lang.CharSequence);
+ }
+
+ public static class Toolbar.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
+ ctor public Toolbar.LayoutParams(android.content.Context, android.util.AttributeSet);
+ ctor public Toolbar.LayoutParams(int, int);
+ ctor public Toolbar.LayoutParams(int, int, int);
+ ctor public Toolbar.LayoutParams(int);
+ ctor public Toolbar.LayoutParams(android.widget.Toolbar.LayoutParams);
+ ctor public Toolbar.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
+ ctor public Toolbar.LayoutParams(android.view.ViewGroup.LayoutParams);
+ field public int gravity;
+ }
+
+ public static abstract interface Toolbar.OnMenuItemClickListener {
+ method public abstract boolean onMenuItemClick(android.view.MenuItem);
+ }
+
public deprecated class TwoLineListItem extends android.widget.RelativeLayout {
ctor public TwoLineListItem(android.content.Context);
ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet);
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index fbe898771856..34b0f3a70332 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -20,9 +20,11 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.view.ActionMode;
import android.view.Gravity;
import android.view.View;
import android.view.ViewDebug;
@@ -30,31 +32,57 @@ import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.Window;
import android.widget.SpinnerAdapter;
+import android.widget.Toolbar;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Map;
/**
- * A window feature at the top of the activity that may display the activity title, navigation
- * modes, and other interactive items.
+ * A primary toolbar within the activity that may display the activity title, application-level
+ * navigation affordances, and other interactive items.
+ *
* <p>Beginning with Android 3.0 (API level 11), the action bar appears at the top of an
* activity's window when the activity uses the system's {@link
* android.R.style#Theme_Holo Holo} theme (or one of its descendant themes), which is the default.
* You may otherwise add the action bar by calling {@link
* android.view.Window#requestFeature requestFeature(FEATURE_ACTION_BAR)} or by declaring it in a
* custom theme with the {@link android.R.styleable#Theme_windowActionBar windowActionBar} property.
- * <p>By default, the action bar shows the application icon on
+ * </p>
+ *
+ * <p>Beginning with Android L (API level 21), the action bar may be represented by any
+ * Toolbar widget within the application layout. The application may signal to the Activity
+ * which Toolbar should be treated as the Activity's action bar. Activities that use this
+ * feature should use one of the supplied <code>.NoActionBar</code> themes, set the
+ * {@link android.R.styleable#Theme_windowActionBar windowActionBar} attribute to <code>false</code>
+ * or otherwise not request the window feature.</p>
+ *
+ * <p>By adjusting the window features requested by the theme and the layouts used for
+ * an Activity's content view, an app can use the standard system action bar on older platform
+ * releases and the newer inline toolbars on newer platform releases. The <code>ActionBar</code>
+ * object obtained from the Activity can be used to control either configuration transparently.</p>
+ *
+ * <p>When using the Holo themes the action bar shows the application icon on
* the left, followed by the activity title. If your activity has an options menu, you can make
* select items accessible directly from the action bar as "action items". You can also
* modify various characteristics of the action bar or remove it completely.</p>
+ *
+ * <p>When using the Quantum themes (default in API 21 or newer) the navigation button
+ * (formerly "Home") takes over the space previously occupied by the application icon.
+ * Apps wishing to express a stronger branding should use their brand colors heavily
+ * in the action bar and other application chrome or use a {@link #setLogo(int) logo}
+ * in place of their standard title text.</p>
+ *
* <p>From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link
* android.app.Activity#getActionBar getActionBar()}.</p>
+ *
* <p>In some cases, the action bar may be overlayed by another bar that enables contextual actions,
* using an {@link android.view.ActionMode}. For example, when the user selects one or more items in
* your activity, you can enable an action mode that offers actions specific to the selected
* items, with a UI that temporarily replaces the action bar. Although the UI may occupy the
* same space, the {@link android.view.ActionMode} APIs are distinct and independent from those for
- * {@link ActionBar}.
+ * {@link ActionBar}.</p>
+ *
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For information about how to use the action bar, including how to add action items, navigation
@@ -73,6 +101,11 @@ public abstract class ActionBar {
* and title text with an optional subtitle. Clicking any of these elements
* will dispatch onOptionsItemSelected to the host Activity with
* a MenuItem with item ID android.R.id.home.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public static final int NAVIGATION_MODE_STANDARD = 0;
@@ -80,12 +113,22 @@ public abstract class ActionBar {
* List navigation mode. Instead of static title text this mode
* presents a list menu for navigation within the activity.
* e.g. this might be presented to the user as a dropdown list.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public static final int NAVIGATION_MODE_LIST = 1;
/**
* Tab navigation mode. Instead of static title text this mode
* presents a series of tabs for navigation within the activity.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public static final int NAVIGATION_MODE_TABS = 2;
@@ -288,6 +331,11 @@ public abstract class ActionBar {
* within the dropdown navigation menu.
* @param callback An OnNavigationListener that will receive events when the user
* selects a navigation item.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void setListNavigationCallbacks(SpinnerAdapter adapter,
OnNavigationListener callback);
@@ -296,6 +344,11 @@ public abstract class ActionBar {
* Set the selected navigation item in list or tabbed navigation modes.
*
* @param position Position of the item to select.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void setSelectedNavigationItem(int position);
@@ -303,6 +356,11 @@ public abstract class ActionBar {
* Get the position of the selected navigation item in list or tabbed navigation modes.
*
* @return Position of the selected item.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract int getSelectedNavigationIndex();
@@ -310,6 +368,11 @@ public abstract class ActionBar {
* Get the number of navigation items present in the current navigation mode.
*
* @return Number of navigation items.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract int getNavigationItemCount();
@@ -507,6 +570,11 @@ public abstract class ActionBar {
* </ul>
*
* @return The current navigation mode.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
@NavigationMode
public abstract int getNavigationMode();
@@ -518,6 +586,11 @@ public abstract class ActionBar {
* @see #NAVIGATION_MODE_STANDARD
* @see #NAVIGATION_MODE_LIST
* @see #NAVIGATION_MODE_TABS
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void setNavigationMode(@NavigationMode int mode);
@@ -539,6 +612,11 @@ public abstract class ActionBar {
* @return A new Tab
*
* @see #addTab(Tab)
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract Tab newTab();
@@ -547,6 +625,11 @@ public abstract class ActionBar {
* If this is the first tab to be added it will become the selected tab.
*
* @param tab Tab to add
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void addTab(Tab tab);
@@ -555,6 +638,11 @@ public abstract class ActionBar {
*
* @param tab Tab to add
* @param setSelected True if the added tab should become the selected tab.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void addTab(Tab tab, boolean setSelected);
@@ -565,6 +653,11 @@ public abstract class ActionBar {
*
* @param tab The tab to add
* @param position The new position of the tab
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void addTab(Tab tab, int position);
@@ -575,6 +668,11 @@ public abstract class ActionBar {
* @param tab The tab to add
* @param position The new position of the tab
* @param setSelected True if the added tab should become the selected tab.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void addTab(Tab tab, int position, boolean setSelected);
@@ -583,6 +681,11 @@ public abstract class ActionBar {
* and another tab will be selected if present.
*
* @param tab The tab to remove
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void removeTab(Tab tab);
@@ -591,11 +694,21 @@ public abstract class ActionBar {
* and another tab will be selected if present.
*
* @param position Position of the tab to remove
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void removeTabAt(int position);
/**
* Remove all tabs from the action bar and deselect the current tab.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void removeAllTabs();
@@ -605,6 +718,11 @@ public abstract class ActionBar {
* <p>Note: If you want to select by index, use {@link #setSelectedNavigationItem(int)}.</p>
*
* @param tab Tab to select
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract void selectTab(Tab tab);
@@ -613,6 +731,11 @@ public abstract class ActionBar {
* one tab present.
*
* @return The currently selected tab or null
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract Tab getSelectedTab();
@@ -621,12 +744,22 @@ public abstract class ActionBar {
*
* @param index Index value in the range 0-get
* @return
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract Tab getTabAt(int index);
/**
* Returns the number of tabs currently registered with the action bar.
* @return Tab count
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public abstract int getTabCount();
@@ -799,8 +932,38 @@ public abstract class ActionBar {
*/
public void setHomeActionContentDescription(int resId) { }
+ /** @hide */
+ public void setDefaultDisplayHomeAsUpEnabled(boolean enabled) {
+ }
+
+ /** @hide */
+ public void setShowHideAnimationEnabled(boolean enabled) {
+ }
+
+ /** @hide */
+ public void onConfigurationChanged(Configuration config) {
+ }
+
+ /** @hide */
+ public void dispatchMenuVisibilityChanged(boolean visible) {
+ }
+
+ /** @hide */
+ public void captureSharedElements(Map<String, View> sharedElements) {
+ }
+
+ /** @hide */
+ public ActionMode startActionMode(ActionMode.Callback callback) {
+ return null;
+ }
+
/**
* Listener interface for ActionBar navigation events.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public interface OnNavigationListener {
/**
@@ -833,6 +996,11 @@ public abstract class ActionBar {
* A tab in the action bar.
*
* <p>Tabs manage the hiding and showing of {@link Fragment}s.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public static abstract class Tab {
/**
@@ -984,6 +1152,11 @@ public abstract class ActionBar {
/**
* Callback interface invoked when a tab is focused, unfocused, added, or removed.
+ *
+ * @deprecated Action bar navigation modes are deprecated and not supported by inline
+ * toolbar action bars. Consider using other
+ * <a href="http://developer.android.com/design/patterns/navigation.html">common
+ * navigation patterns</a> instead.
*/
public interface TabListener {
/**
@@ -1025,27 +1198,27 @@ public abstract class ActionBar {
*
* @attr ref android.R.styleable#ActionBar_LayoutParams_layout_gravity
*/
- public static class LayoutParams extends MarginLayoutParams {
+ public static class LayoutParams extends ViewGroup.MarginLayoutParams {
/**
* Gravity for the view associated with these LayoutParams.
*
* @see android.view.Gravity
*/
@ViewDebug.ExportedProperty(category = "layout", mapping = {
- @ViewDebug.IntToString(from = -1, to = "NONE"),
- @ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"),
- @ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"),
- @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"),
- @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"),
- @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"),
- @ViewDebug.IntToString(from = Gravity.START, to = "START"),
- @ViewDebug.IntToString(from = Gravity.END, to = "END"),
- @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"),
- @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"),
- @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
- @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"),
- @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"),
- @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL")
+ @ViewDebug.IntToString(from = -1, to = "NONE"),
+ @ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"),
+ @ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"),
+ @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"),
+ @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"),
+ @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"),
+ @ViewDebug.IntToString(from = Gravity.START, to = "START"),
+ @ViewDebug.IntToString(from = Gravity.END, to = "END"),
+ @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"),
+ @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"),
+ @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
+ @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"),
+ @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"),
+ @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL")
})
public int gravity = Gravity.NO_GRAVITY;
@@ -1062,12 +1235,10 @@ public abstract class ActionBar {
public LayoutParams(int width, int height) {
super(width, height);
- this.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
}
public LayoutParams(int width, int height, int gravity) {
super(width, height);
- this.gravity = gravity;
}
public LayoutParams(int gravity) {
@@ -1076,12 +1247,14 @@ public abstract class ActionBar {
public LayoutParams(LayoutParams source) {
super(source);
-
- this.gravity = source.gravity;
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
+
+ public LayoutParams(MarginLayoutParams source) {
+ super(source);
+ }
}
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 20e7311b94d5..b18eb983fcc2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -21,9 +21,10 @@ import android.transition.Scene;
import android.transition.Transition;
import android.transition.TransitionManager;
import android.util.ArrayMap;
-import android.util.Pair;
import android.util.SuperNotCalledException;
-import com.android.internal.app.ActionBarImpl;
+import android.widget.Toolbar;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.app.ToolbarActionBar;
import com.android.internal.policy.PolicyManager;
import android.annotation.IntDef;
@@ -723,7 +724,7 @@ public class Activity extends ContextThemeWrapper
/*package*/ boolean mWindowAdded = false;
/*package*/ boolean mVisibleFromServer = false;
/*package*/ boolean mVisibleFromClient = true;
- /*package*/ ActionBarImpl mActionBar = null;
+ /*package*/ ActionBar mActionBar = null;
private boolean mEnableDefaultActionBarUp;
private CharSequence mTitle;
@@ -772,7 +773,6 @@ public class Activity extends ContextThemeWrapper
private Thread mUiThread;
final Handler mHandler = new Handler();
- private ActivityOptions mTransitionActivityOptions;
/** Return the intent that started this activity. */
public Intent getIntent() {
@@ -1398,6 +1398,9 @@ public class Activity extends ContextThemeWrapper
protected void onStop() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStop " + this);
if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
+ if (mWindow != null) {
+ mWindow.restoreViewVisibilityAfterTransitionToCallee();
+ }
getApplication().dispatchActivityStopped(this);
mTranslucentCallback = null;
mCalled = true;
@@ -1906,15 +1909,39 @@ public class Activity extends ContextThemeWrapper
*/
@Nullable
public ActionBar getActionBar() {
- initActionBar();
+ initWindowDecorActionBar();
return mActionBar;
}
+
+ /**
+ * Set a {@link android.widget.Toolbar Toolbar} to act as the {@link ActionBar} for this
+ * Activity window.
+ *
+ * <p>When set to a non-null value the {@link #getActionBar()} method will return
+ * an {@link ActionBar} object that can be used to control the given toolbar as if it were
+ * a traditional window decor action bar. The toolbar's menu will be populated with the
+ * Activity's options menu and the navigation button will be wired through the standard
+ * {@link android.R.id#home home} menu select action.</p>
+ *
+ * <p>In order to use a Toolbar within the Activity's window content the application
+ * must not request the window feature {@link Window#FEATURE_ACTION_BAR FEATURE_ACTION_BAR}.</p>
+ *
+ * @param actionBar Toolbar to set as the Activity's action bar
+ */
+ public void setActionBar(@Nullable Toolbar actionBar) {
+ if (getActionBar() instanceof WindowDecorActionBar) {
+ throw new IllegalStateException("This Activity already has an action bar supplied " +
+ "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " +
+ "android:windowActionBar to false in your theme to use a Toolbar instead.");
+ }
+ mActionBar = new ToolbarActionBar(actionBar);
+ }
/**
* Creates a new ActionBar, locates the inflated ActionBarView,
* initializes the ActionBar with the view, and sets mActionBar.
*/
- private void initActionBar() {
+ private void initWindowDecorActionBar() {
Window window = getWindow();
// Initializing the window decor can change window feature flags.
@@ -1925,7 +1952,7 @@ public class Activity extends ContextThemeWrapper
return;
}
- mActionBar = new ActionBarImpl(this);
+ mActionBar = new WindowDecorActionBar(this);
mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);
mWindow.setDefaultIcon(mActivityInfo.getIconResource());
@@ -1943,7 +1970,7 @@ public class Activity extends ContextThemeWrapper
*/
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
- initActionBar();
+ initWindowDecorActionBar();
}
/**
@@ -1963,7 +1990,7 @@ public class Activity extends ContextThemeWrapper
*/
public void setContentView(View view) {
getWindow().setContentView(view);
- initActionBar();
+ initWindowDecorActionBar();
}
/**
@@ -1979,7 +2006,7 @@ public class Activity extends ContextThemeWrapper
*/
public void setContentView(View view, ViewGroup.LayoutParams params) {
getWindow().setContentView(view, params);
- initActionBar();
+ initWindowDecorActionBar();
}
/**
@@ -1991,7 +2018,7 @@ public class Activity extends ContextThemeWrapper
*/
public void addContentView(View view, ViewGroup.LayoutParams params) {
getWindow().addContentView(view, params);
- initActionBar();
+ initWindowDecorActionBar();
}
/**
@@ -2274,7 +2301,7 @@ public class Activity extends ContextThemeWrapper
*/
public void onBackPressed() {
if (!mFragments.popBackStackImmediate()) {
- finish();
+ finishWithTransition();
}
}
@@ -2636,7 +2663,7 @@ public class Activity extends ContextThemeWrapper
*/
public boolean onMenuOpened(int featureId, Menu menu) {
if (featureId == Window.FEATURE_ACTION_BAR) {
- initActionBar();
+ initWindowDecorActionBar();
if (mActionBar != null) {
mActionBar.dispatchMenuVisibilityChanged(true);
} else {
@@ -2717,7 +2744,7 @@ public class Activity extends ContextThemeWrapper
break;
case Window.FEATURE_ACTION_BAR:
- initActionBar();
+ initWindowDecorActionBar();
mActionBar.dispatchMenuVisibilityChanged(false);
break;
}
@@ -3417,7 +3444,7 @@ public class Activity extends ContextThemeWrapper
public MenuInflater getMenuInflater() {
// Make sure that action views can get an appropriate theme.
if (mMenuInflater == null) {
- initActionBar();
+ initWindowDecorActionBar();
if (mActionBar != null) {
mMenuInflater = new MenuInflater(mActionBar.getThemedContext(), this);
} else {
@@ -3457,8 +3484,7 @@ public class Activity extends ContextThemeWrapper
public void startActivityForResult(Intent intent, int requestCode) {
Bundle options = null;
if (mWindow.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
- final Pair<View, String>[] noSharedElements = null;
- options = ActivityOptions.makeSceneTransitionAnimation(noSharedElements).toBundle();
+ options = ActivityOptions.makeSceneTransitionAnimation().toBundle();
}
startActivityForResult(intent, requestCode, options);
}
@@ -3506,7 +3532,7 @@ public class Activity extends ContextThemeWrapper
mActionBar.captureSharedElements(sharedElementMap);
activityOptions.addSharedElements(sharedElementMap);
}
- options = mWindow.startExitTransition(activityOptions);
+ options = mWindow.startExitTransitionToCallee(options);
}
}
if (mParent == null) {
@@ -4361,6 +4387,23 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Reverses the Activity Scene entry Transition and triggers the calling Activity
+ * to reverse its exit Transition. When the exit Transition completes,
+ * {@link #finish()} is called. If no entry Transition was used, finish() is called
+ * immediately and the Activity exit Transition is run.
+ * @see android.view.Window#setTriggerEarlySceneTransition(boolean, boolean)
+ * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.View, String)
+ */
+ public void finishWithTransition() {
+ mWindow.startExitTransitionToCaller(new Runnable() {
+ @Override
+ public void run() {
+ finish();
+ }
+ });
+ }
+
+ /**
* Force finish another activity that you had previously started with
* {@link #startActivityForResult}.
*
@@ -5139,7 +5182,7 @@ public class Activity extends ContextThemeWrapper
@Nullable
@Override
public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
- initActionBar();
+ initWindowDecorActionBar();
if (mActionBar != null) {
return mActionBar.startActionMode(callback);
}
@@ -5370,43 +5413,34 @@ public class Activity extends ContextThemeWrapper
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
- mTransitionActivityOptions = null;
- Window.SceneTransitionListener sceneTransitionListener = null;
- if (options != null) {
- ActivityOptions activityOptions = new ActivityOptions(options);
- if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
- mTransitionActivityOptions = activityOptions;
- sceneTransitionListener = new Window.SceneTransitionListener() {
- @Override
- public void nullPendingTransition() {
- overridePendingTransition(0, 0);
- }
-
- @Override
- public void convertFromTranslucent() {
- Activity.this.convertFromTranslucent();
- }
-
- @Override
- public void convertToTranslucent() {
- Activity.this.convertToTranslucent(null);
- }
+ Window.SceneTransitionListener sceneTransitionListener
+ = new Window.SceneTransitionListener() {
+ @Override
+ public void nullPendingTransition() {
+ overridePendingTransition(0, 0);
+ }
- @Override
- public void sharedElementStart(Transition transition) {
- Activity.this.onCaptureSharedElementStart(transition);
- }
+ @Override
+ public void convertFromTranslucent() {
+ Activity.this.convertFromTranslucent();
+ }
- @Override
- public void sharedElementEnd() {
- Activity.this.onCaptureSharedElementEnd();
- }
- };
+ @Override
+ public void convertToTranslucent() {
+ Activity.this.convertToTranslucent(null);
+ }
+ @Override
+ public void sharedElementStart(Transition transition) {
+ Activity.this.onCaptureSharedElementStart(transition);
}
- }
- mWindow.setTransitionOptions(mTransitionActivityOptions, sceneTransitionListener);
+ @Override
+ public void sharedElementEnd() {
+ Activity.this.onCaptureSharedElementEnd();
+ }
+ };
+ mWindow.setTransitionOptions(options, sceneTransitionListener);
}
/** @hide */
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 07247ffc3300..438458083a49 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -20,8 +20,10 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.transition.Transition;
import android.util.Log;
import android.util.Pair;
@@ -136,6 +138,11 @@ public class ActivityOptions {
/** @hide */
public static final int ANIM_SCENE_TRANSITION = 5;
+ private static final int MSG_SET_LISTENER = 100;
+ private static final int MSG_HIDE_SHARED_ELEMENTS = 101;
+ private static final int MSG_PREPARE_RESTORE = 102;
+ private static final int MSG_RESTORE = 103;
+
private String mPackageName;
private int mAnimationType = ANIM_NONE;
private int mCustomEnterResId;
@@ -146,7 +153,7 @@ public class ActivityOptions {
private int mStartWidth;
private int mStartHeight;
private IRemoteCallback mAnimationStartedListener;
- private IRemoteCallback mTransitionCompleteListener;
+ private ResultReceiver mTransitionCompleteListener;
private ArrayList<String> mSharedElementNames;
private ArrayList<String> mLocalElementNames;
@@ -428,8 +435,7 @@ public class ActivityOptions {
break;
case ANIM_SCENE_TRANSITION:
- mTransitionCompleteListener = IRemoteCallback.Stub.asInterface(
- opts.getBinder(KEY_TRANSITION_COMPLETE_LISTENER));
+ mTransitionCompleteListener = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
mSharedElementNames = opts.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
mLocalElementNames = opts.getStringArrayList(KEY_LOCAL_ELEMENT_NAMES);
break;
@@ -495,7 +501,6 @@ public class ActivityOptions {
/** @hide */
public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target,
ArrayList<String> sharedElementNames) {
- boolean listenerSent = false;
if (mTransitionCompleteListener != null) {
IRemoteCallback callback = new IRemoteCallback.Stub() {
@Override
@@ -510,27 +515,28 @@ public class ActivityOptions {
Bundle bundle = new Bundle();
bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder());
bundle.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, sharedElementNames);
- try {
- mTransitionCompleteListener.sendResult(bundle);
- listenerSent = true;
- } catch (RemoteException e) {
- Log.w(TAG, "Couldn't retrieve transition notifications", e);
- }
- }
- if (!listenerSent) {
- target.sharedElementTransitionComplete(null);
- target.exitTransitionComplete();
+ mTransitionCompleteListener.send(MSG_SET_LISTENER, bundle);
}
}
/** @hide */
public void dispatchSharedElementsReady() {
if (mTransitionCompleteListener != null) {
- try {
- mTransitionCompleteListener.sendResult(null);
- } catch (RemoteException e) {
- Log.w(TAG, "Couldn't synchronize shared elements", e);
- }
+ mTransitionCompleteListener.send(MSG_HIDE_SHARED_ELEMENTS, null);
+ }
+ }
+
+ /** @hide */
+ public void dispatchPrepareRestore() {
+ if (mTransitionCompleteListener != null) {
+ mTransitionCompleteListener.send(MSG_PREPARE_RESTORE, null);
+ }
+ }
+
+ /** @hide */
+ public void dispatchRestore(Bundle sharedElementsArgs) {
+ if (mTransitionCompleteListener != null) {
+ mTransitionCompleteListener.send(MSG_RESTORE, sharedElementsArgs);
}
}
@@ -658,8 +664,7 @@ public class ActivityOptions {
case ANIM_SCENE_TRANSITION:
b.putInt(KEY_ANIM_TYPE, mAnimationType);
if (mTransitionCompleteListener != null) {
- b.putBinder(KEY_TRANSITION_COMPLETE_LISTENER,
- mTransitionCompleteListener.asBinder());
+ b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionCompleteListener);
}
b.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, mSharedElementNames);
b.putStringArrayList(KEY_LOCAL_ELEMENT_NAMES, mLocalElementNames);
@@ -710,13 +715,13 @@ public class ActivityOptions {
Bundle getSharedElementExitState();
void acceptedSharedElements(ArrayList<String> sharedElementNames);
void hideSharedElements();
+ void restore(Bundle sharedElementState);
+ void prepareForRestore();
}
- private static class ExitTransitionListener extends IRemoteCallback.Stub
+ private static class ExitTransitionListener extends ResultReceiver
implements Transition.TransitionListener {
private boolean mSharedElementNotified;
- private Transition mExitTransition;
- private Transition mSharedElementTransition;
private IRemoteCallback mTransitionCompleteCallback;
private boolean mExitComplete;
private boolean mSharedElementComplete;
@@ -724,25 +729,40 @@ public class ActivityOptions {
public ExitTransitionListener(Transition exitTransition, Transition sharedElementTransition,
SharedElementSource sharedElementSource) {
+ super(null);
mSharedElementSource = sharedElementSource;
- mExitTransition = exitTransition;
- mExitTransition.addListener(this);
- mSharedElementTransition = sharedElementTransition;
- mSharedElementTransition.addListener(this);
+ exitTransition.addListener(this);
+ sharedElementTransition.addListener(new Transition.TransitionListenerAdapter() {
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ mSharedElementComplete = true;
+ notifySharedElement();
+ transition.removeListener(this);
+ }
+ });
}
@Override
- public void sendResult(Bundle data) throws RemoteException {
- if (data != null) {
- mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(
- data.getBinder(KEY_TRANSITION_TARGET_LISTENER));
- ArrayList<String> sharedElementNames
- = data.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
- mSharedElementSource.acceptedSharedElements(sharedElementNames);
- notifySharedElement();
- notifyExit();
- } else {
- mSharedElementSource.hideSharedElements();
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ switch (resultCode) {
+ case MSG_SET_LISTENER:
+ IBinder listener = resultData.getBinder(KEY_TRANSITION_TARGET_LISTENER);
+ mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(listener);
+ ArrayList<String> sharedElementNames
+ = resultData.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
+ mSharedElementSource.acceptedSharedElements(sharedElementNames);
+ notifySharedElement();
+ notifyExit();
+ break;
+ case MSG_HIDE_SHARED_ELEMENTS:
+ mSharedElementSource.hideSharedElements();
+ break;
+ case MSG_PREPARE_RESTORE:
+ mSharedElementSource.prepareForRestore();
+ break;
+ case MSG_RESTORE:
+ mSharedElementSource.restore(resultData);
+ break;
}
}
@@ -752,15 +772,9 @@ public class ActivityOptions {
@Override
public void onTransitionEnd(Transition transition) {
- if (transition == mExitTransition) {
- mExitComplete = true;
- notifyExit();
- mExitTransition.removeListener(this);
- } else {
- mSharedElementComplete = true;
- notifySharedElement();
- mSharedElementTransition.removeListener(this);
- }
+ mExitComplete = true;
+ notifyExit();
+ transition.removeListener(this);
}
@Override
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index fb96d8d4d07d..07583fdd4974 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -17,7 +17,7 @@
package android.app;
import android.content.pm.ApplicationInfo;
-import com.android.internal.app.ActionBarImpl;
+import com.android.internal.app.WindowDecorActionBar;
import com.android.internal.policy.PolicyManager;
import android.content.ComponentName;
@@ -87,7 +87,7 @@ public class Dialog implements DialogInterface, Window.Callback,
final WindowManager mWindowManager;
Window mWindow;
View mDecor;
- private ActionBarImpl mActionBar;
+ private ActionBar mActionBar;
/**
* This field should be made private, so it is hidden from the SDK.
* {@hide}
@@ -280,7 +280,7 @@ public class Dialog implements DialogInterface, Window.Callback,
final ApplicationInfo info = mContext.getApplicationInfo();
mWindow.setDefaultIcon(info.icon);
mWindow.setDefaultLogo(info.logo);
- mActionBar = new ActionBarImpl(this);
+ mActionBar = new WindowDecorActionBar(this);
}
WindowManager.LayoutParams l = mWindow.getAttributes();
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 0c22740b6e00..c6731c9df423 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -166,9 +166,11 @@ public class UiModeManager {
/**
* Return the current running mode type. May be one of
* {@link Configuration#UI_MODE_TYPE_NORMAL Configuration.UI_MODE_TYPE_NORMAL},
- * {@link Configuration#UI_MODE_TYPE_DESK Configuration.UI_MODE_TYPE_DESK}, or
- * {@link Configuration#UI_MODE_TYPE_CAR Configuration.UI_MODE_TYPE_CAR}, or
- * {@link Configuration#UI_MODE_TYPE_TELEVISION Configuration.UI_MODE_TYPE_APPLIANCE}.
+ * {@link Configuration#UI_MODE_TYPE_DESK Configuration.UI_MODE_TYPE_DESK},
+ * {@link Configuration#UI_MODE_TYPE_CAR Configuration.UI_MODE_TYPE_CAR},
+ * {@link Configuration#UI_MODE_TYPE_TELEVISION Configuration.UI_MODE_TYPE_TELEVISION},
+ * {@link Configuration#UI_MODE_TYPE_APPLIANCE Configuration.UI_MODE_TYPE_APPLIANCE}, or
+ * {@link Configuration#UI_MODE_TYPE_WATCH Configuration.UI_MODE_TYPE_WATCH}.
*/
public int getCurrentModeType() {
if (mService != null) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3fdaef2c4d69..27e526b2a31d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -573,6 +573,9 @@ public abstract class Context {
* Open a private file associated with this Context's application package
* for writing. Creates the file if it doesn't already exist.
*
+ * <p>No permissions are required to invoke this method, since it uses internal
+ * storage.
+ *
* @param name The name of the file to open; can not contain path
* separators.
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
@@ -630,6 +633,9 @@ public abstract class Context {
* Returns the absolute path to the directory on the filesystem where
* files created with {@link #openFileOutput} are stored.
*
+ * <p>No permissions are required to read or write to the returned path, since this
+ * path is internal storage.
+ *
* @return The path of the directory holding application files.
*
* @see #openFileOutput
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d189a344fdbd..9881428865c4 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2608,6 +2608,23 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.USER_INFO_CHANGED";
/**
+ * Broadcast sent to the primary user when an associated managed profile is added (the profile
+ * was created and is ready to be used). Carries an extra {@link #EXTRA_USER} that specifies
+ * the UserHandle of the profile that was added. This is only sent to registered receivers,
+ * not manifest receivers.
+ */
+ public static final String ACTION_MANAGED_PROFILE_ADDED =
+ "android.intent.action.MANAGED_PROFILE_ADDED";
+
+ /**
+ * Broadcast sent to the primary user when an associated managed profile is removed. Carries an
+ * extra {@link #EXTRA_USER} that specifies the UserHandle of the profile that was removed. This
+ * is only sent to registered receivers, not manifest receivers.
+ */
+ public static final String ACTION_MANAGED_PROFILE_REMOVED =
+ "android.intent.action.MANAGED_PROFILE_REMOVED";
+
+ /**
* Sent when the user taps on the clock widget in the system's "quick settings" area.
*/
public static final String ACTION_QUICK_CLOCK =
@@ -3301,15 +3318,23 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.extra.ALLOW_MULTIPLE";
/**
- * The userHandle carried with broadcast intents related to addition, removal and switching of
- * users
- * - {@link #ACTION_USER_ADDED}, {@link #ACTION_USER_REMOVED} and {@link #ACTION_USER_SWITCHED}.
+ * The integer userHandle carried with broadcast intents related to addition, removal and
+ * switching of users and managed profiles - {@link #ACTION_USER_ADDED},
+ * {@link #ACTION_USER_REMOVED} and {@link #ACTION_USER_SWITCHED}.
+ *
* @hide
*/
public static final String EXTRA_USER_HANDLE =
"android.intent.extra.user_handle";
/**
+ * The UserHandle carried with broadcasts intents related to addition and removal of managed
+ * profiles - {@link #ACTION_MANAGED_PROFILE_ADDED} and {@link #ACTION_MANAGED_PROFILE_REMOVED}.
+ */
+ public static final String EXTRA_USER =
+ "android.intent.extra.user";
+
+ /**
* Extra used in the response from a BroadcastReceiver that handles
* {@link #ACTION_GET_RESTRICTION_ENTRIES}. The type of the extra is
* <code>ArrayList&lt;RestrictionEntry&gt;</code>.
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 48b6fca7b2d3..a07fc9708b7f 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -440,6 +440,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
* resource qualifier. */
public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
+ /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
+ * value that corresponds to the
+ * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a>
+ * resource qualifier. */
+ public static final int UI_MODE_TYPE_WATCH = 0x06;
/** Constant for {@link #uiMode}: bits that encode the night mode. */
public static final int UI_MODE_NIGHT_MASK = 0x30;
@@ -462,8 +467,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
* device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
* {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
- * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION}, or
- * {@link #UI_MODE_TYPE_APPLIANCE}.
+ * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
+ * {@link #UI_MODE_TYPE_APPLIANCE}, or {@link #UI_MODE_TYPE_WATCH}.
*
* <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
* is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
@@ -700,6 +705,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
case UI_MODE_TYPE_CAR: sb.append(" car"); break;
case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
+ case UI_MODE_TYPE_WATCH: sb.append(" watch"); break;
default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
}
switch ((uiMode&UI_MODE_NIGHT_MASK)) {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index d6eafc6e4018..4879c2382afd 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1585,6 +1585,15 @@ public class Resources {
/** Resource identifier for the theme. */
private int mThemeResId = 0;
+
+ // Needed by layoutlib.
+ /*package*/ long getNativeTheme() {
+ return mTheme;
+ }
+
+ /*package*/ int getAppliedStyleResId() {
+ return mThemeResId;
+ }
}
/**
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index d03b0c5ba3e7..be3c0cc69883 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -23,7 +23,7 @@ import android.os.WorkSource;
interface IPowerManager
{
- // WARNING: The first four methods must remain the first three methods because their
+ // WARNING: The first five methods must remain the first five methods because their
// transaction numbers must not change unless IPowerManager.cpp is also updated.
void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws,
String historyTag);
@@ -31,6 +31,7 @@ interface IPowerManager
int uidtoblame);
void releaseWakeLock(IBinder lock, int flags);
void updateWakeLockUids(IBinder lock, in int[] uids);
+ oneway void powerHint(int hintId, int data);
void updateWakeLockWorkSource(IBinder lock, in WorkSource ws, String historyTag);
boolean isWakeLockLevelSupported(int level);
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 535eee1397ed..638ef22fe3e2 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -433,7 +433,7 @@ public class StaticLayout extends Layout {
}
if (mLineCount >= mMaximumVisibleLineCount) {
- break;
+ return;
}
}
}
diff --git a/core/java/android/transition/CircularPropagation.java b/core/java/android/transition/CircularPropagation.java
new file mode 100644
index 000000000000..18a3d229cc6c
--- /dev/null
+++ b/core/java/android/transition/CircularPropagation.java
@@ -0,0 +1,103 @@
+/*
+ * 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.transition;
+
+import android.graphics.Rect;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * A propagation that varies with the distance to the epicenter of the Transition
+ * or center of the scene if no epicenter exists. When a View is visible in the
+ * start of the transition, Views farther from the epicenter will transition
+ * sooner than Views closer to the epicenter. When a View is not in the start
+ * of the transition or is not visible at the start of the transition, it will
+ * transition sooner when closer to the epicenter and later when farther from
+ * the epicenter. This is the default TransitionPropagation used with
+ * {@link android.transition.Explode}.
+ */
+public class CircularPropagation extends VisibilityPropagation {
+ private static final String TAG = "CircularPropagation";
+
+ private float mPropagationSpeed = 4.0f;
+
+ /**
+ * Sets the speed at which transition propagation happens, relative to the duration of the
+ * Transition. A <code>propagationSpeed</code> of 1 means that a View centered farthest from
+ * the epicenter and View centered at the epicenter will have a difference
+ * in start delay of approximately the duration of the Transition. A speed of 2 means the
+ * start delay difference will be approximately half of the duration of the transition. A
+ * value of 0 is illegal, but negative values will invert the propagation.
+ *
+ * @param propagationSpeed The speed at which propagation occurs, relative to the duration
+ * of the transition. A speed of 4 means it works 4 times as fast
+ * as the duration of the transition. May not be 0.
+ */
+ public void setPropagationSpeed(float propagationSpeed) {
+ if (propagationSpeed == 0) {
+ throw new IllegalArgumentException("propagationSpeed may not be 0");
+ }
+ mPropagationSpeed = propagationSpeed;
+ }
+
+ @Override
+ public long getStartDelay(ViewGroup sceneRoot, Transition transition,
+ TransitionValues startValues, TransitionValues endValues) {
+ if (startValues == null && endValues == null) {
+ return 0;
+ }
+ int directionMultiplier = 1;
+ TransitionValues positionValues;
+ if (endValues == null || getViewVisibility(startValues) == View.VISIBLE) {
+ positionValues = startValues;
+ directionMultiplier = -1;
+ } else {
+ positionValues = endValues;
+ }
+
+ int viewCenterX = getViewX(positionValues);
+ int viewCenterY = getViewY(positionValues);
+
+ Rect epicenter = transition.getEpicenter();
+ int epicenterX;
+ int epicenterY;
+ if (epicenter != null) {
+ epicenterX = epicenter.centerX();
+ epicenterY = epicenter.centerY();
+ } else {
+ int[] loc = new int[2];
+ sceneRoot.getLocationOnScreen(loc);
+ epicenterX = Math.round(loc[0] + (sceneRoot.getWidth() / 2)
+ + sceneRoot.getTranslationX());
+ epicenterY = Math.round(loc[1] + (sceneRoot.getHeight() / 2)
+ + sceneRoot.getTranslationY());
+ }
+ float distance = distance(viewCenterX, viewCenterY, epicenterX, epicenterY);
+ float maxDistance = distance(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight());
+ float distanceFraction = distance/maxDistance;
+
+ return Math.round(transition.getDuration() * directionMultiplier / mPropagationSpeed
+ * distanceFraction);
+ }
+
+ private static float distance(float x1, float y1, float x2, float y2) {
+ float x = x2 - x1;
+ float y = y2 - y1;
+ return FloatMath.sqrt((x * x) + (y * y));
+ }
+}
diff --git a/core/java/android/transition/Explode.java b/core/java/android/transition/Explode.java
new file mode 100644
index 000000000000..fae527c26789
--- /dev/null
+++ b/core/java/android/transition/Explode.java
@@ -0,0 +1,228 @@
+/*
+ * 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.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+
+/**
+ * This transition tracks changes to the visibility of target views in the
+ * start and end scenes and moves views in or out from the edges of the
+ * scene. Visibility is determined by both the
+ * {@link View#setVisibility(int)} state of the view as well as whether it
+ * is parented in the current view hierarchy. Disappearing Views are
+ * limited as described in {@link Visibility#onDisappear(android.view.ViewGroup,
+ * TransitionValues, int, TransitionValues, int)}.
+ * <p>Views move away from the focal View or the center of the Scene if
+ * no epicenter was provided.</p>
+ */
+public class Explode extends Visibility {
+ private static final TimeInterpolator sDecelerate = new DecelerateInterpolator();
+ private static final TimeInterpolator sAccelerate = new AccelerateInterpolator();
+ private static final String TAG = "Explode";
+
+ private static final String PROPNAME_SCREEN_BOUNDS = "android:out:screenBounds";
+
+ private int[] mTempLoc = new int[2];
+
+ public Explode() {
+ setPropagation(new CircularPropagation());
+ }
+
+ private void captureValues(TransitionValues transitionValues) {
+ View view = transitionValues.view;
+ view.getLocationOnScreen(mTempLoc);
+ int left = mTempLoc[0] + Math.round(view.getTranslationX());
+ int top = mTempLoc[1] + Math.round(view.getTranslationY());
+ int right = left + view.getWidth();
+ int bottom = top + view.getHeight();
+ transitionValues.values.put(PROPNAME_SCREEN_BOUNDS, new Rect(left, top, right, bottom));
+ }
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ captureValues(transitionValues);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ captureValues(transitionValues);
+ }
+
+ private Animator createAnimation(final View view, float startX, float startY, float endX,
+ float endY, float terminalX, float terminalY, TimeInterpolator interpolator) {
+ view.setTranslationX(startX);
+ view.setTranslationY(startY);
+ if (startY == endY && startX == endX) {
+ return null;
+ }
+ Path path = new Path();
+ path.moveTo(startX, startY);
+ path.lineTo(endX, endY);
+ ObjectAnimator pathAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X,
+ View.TRANSLATION_Y, path);
+ pathAnimator.setInterpolator(interpolator);
+ OutAnimatorListener listener = new OutAnimatorListener(view, terminalX, terminalY,
+ endX, endY);
+ pathAnimator.addListener(listener);
+ pathAnimator.addPauseListener(listener);
+
+ return pathAnimator;
+ }
+
+ @Override
+ public Animator onAppear(ViewGroup sceneRoot, View view,
+ TransitionValues startValues, TransitionValues endValues) {
+ if (endValues == null) {
+ return null;
+ }
+ Rect bounds = (Rect) endValues.values.get(PROPNAME_SCREEN_BOUNDS);
+ calculateOut(sceneRoot, bounds, mTempLoc);
+
+ final float endX = view.getTranslationX();
+ final float startX = endX + mTempLoc[0];
+ final float endY = view.getTranslationY();
+ final float startY = endY + mTempLoc[1];
+
+ return createAnimation(view, startX, startY, endX, endY, endX, endY, sDecelerate);
+ }
+
+ @Override
+ public Animator onDisappear(ViewGroup sceneRoot, View view,
+ TransitionValues startValues, TransitionValues endValues) {
+ Rect bounds = (Rect) startValues.values.get(PROPNAME_SCREEN_BOUNDS);
+ calculateOut(sceneRoot, bounds, mTempLoc);
+
+ final float startX = view.getTranslationX();
+ final float endX = startX + mTempLoc[0];
+ final float startY = view.getTranslationY();
+ final float endY = startY + mTempLoc[1];
+
+ return createAnimation(view, startX, startY, endX, endY, startX, startY,
+ sAccelerate);
+ }
+
+ private void calculateOut(View sceneRoot, Rect bounds, int[] outVector) {
+ sceneRoot.getLocationOnScreen(mTempLoc);
+ int sceneRootX = mTempLoc[0];
+ int sceneRootY = mTempLoc[1];
+ int focalX;
+ int focalY;
+
+ Rect epicenter = getEpicenter();
+ if (epicenter == null) {
+ focalX = sceneRootX + (sceneRoot.getWidth() / 2)
+ + Math.round(sceneRoot.getTranslationX());
+ focalY = sceneRootY + (sceneRoot.getHeight() / 2)
+ + Math.round(sceneRoot.getTranslationY());
+ } else {
+ focalX = epicenter.centerX();
+ focalY = epicenter.centerY();
+ }
+
+ int centerX = bounds.centerX();
+ int centerY = bounds.centerY();
+ float xVector = centerX - focalX;
+ float yVector = centerY - focalY;
+
+ if (xVector == 0 && yVector == 0) {
+ // Random direction when View is centered on focal View.
+ xVector = (float)(Math.random() * 2) - 1;
+ yVector = (float)(Math.random() * 2) - 1;
+ }
+ float vectorSize = calculateDistance(xVector, yVector);
+ xVector /= vectorSize;
+ yVector /= vectorSize;
+
+ float maxDistance =
+ calculateMaxDistance(sceneRoot, focalX - sceneRootX, focalY - sceneRootY);
+
+ outVector[0] = Math.round(maxDistance * xVector);
+ outVector[1] = Math.round(maxDistance * yVector);
+ }
+
+ private static float calculateMaxDistance(View sceneRoot, int focalX, int focalY) {
+ int maxX = Math.max(focalX, sceneRoot.getWidth() - focalX);
+ int maxY = Math.max(focalY, sceneRoot.getHeight() - focalY);
+ return calculateDistance(maxX, maxY);
+ }
+
+ private static float calculateDistance(float x, float y) {
+ return FloatMath.sqrt((x * x) + (y * y));
+ }
+
+ private static class OutAnimatorListener extends AnimatorListenerAdapter {
+ private final View mView;
+ private boolean mCanceled = false;
+ private float mPausedX;
+ private float mPausedY;
+ private final float mTerminalX;
+ private final float mTerminalY;
+ private final float mEndX;
+ private final float mEndY;
+
+ public OutAnimatorListener(View view, float terminalX, float terminalY,
+ float endX, float endY) {
+ mView = view;
+ mTerminalX = terminalX;
+ mTerminalY = terminalY;
+ mEndX = endX;
+ mEndY = endY;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ mView.setTranslationX(mTerminalX);
+ mView.setTranslationY(mTerminalY);
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ if (!mCanceled) {
+ mView.setTranslationX(mTerminalX);
+ mView.setTranslationY(mTerminalY);
+ }
+ }
+
+ @Override
+ public void onAnimationPause(Animator animator) {
+ mPausedX = mView.getTranslationX();
+ mPausedY = mView.getTranslationY();
+ mView.setTranslationY(mEndX);
+ mView.setTranslationY(mEndY);
+ }
+
+ @Override
+ public void onAnimationResume(Animator animator) {
+ mView.setTranslationX(mPausedX);
+ mView.setTranslationY(mPausedY);
+ }
+ }
+}
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index 8edb1ff74405..08e27d33ff47 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -59,8 +59,6 @@ public class Fade extends Visibility {
private static boolean DBG = Transition.DBG && false;
private static final String LOG_TAG = "Fade";
- private static final String PROPNAME_SCREEN_X = "android:fade:screenX";
- private static final String PROPNAME_SCREEN_Y = "android:fade:screenY";
/**
* Fading mode used in {@link #Fade(int)} to make the transition
@@ -98,245 +96,81 @@ public class Fade extends Visibility {
/**
* Utility method to handle creating and running the Animator.
*/
- private Animator createAnimation(View view, float startAlpha, float endAlpha,
- AnimatorListenerAdapter listener) {
+ private Animator createAnimation(View view, float startAlpha, float endAlpha) {
if (startAlpha == endAlpha) {
- // run listener if we're noop'ing the animation, to get the end-state results now
- if (listener != null) {
- listener.onAnimationEnd(null);
- }
return null;
}
- final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "transitionAlpha", startAlpha,
- endAlpha);
+ view.setTransitionAlpha(startAlpha);
+ final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "transitionAlpha", endAlpha);
if (DBG) {
Log.d(LOG_TAG, "Created animator " + anim);
}
- if (listener != null) {
- anim.addListener(listener);
- anim.addPauseListener(listener);
- }
+ FadeAnimatorListener listener = new FadeAnimatorListener(view, endAlpha);
+ anim.addListener(listener);
+ anim.addPauseListener(listener);
return anim;
}
- private void captureValues(TransitionValues transitionValues) {
- int[] loc = new int[2];
- transitionValues.view.getLocationOnScreen(loc);
- transitionValues.values.put(PROPNAME_SCREEN_X, loc[0]);
- transitionValues.values.put(PROPNAME_SCREEN_Y, loc[1]);
- }
-
- @Override
- public void captureStartValues(TransitionValues transitionValues) {
- super.captureStartValues(transitionValues);
- captureValues(transitionValues);
- }
-
@Override
- public Animator onAppear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
+ public Animator onAppear(ViewGroup sceneRoot, View view,
+ TransitionValues startValues,
+ TransitionValues endValues) {
if ((mFadingMode & IN) != IN || endValues == null) {
return null;
}
- final View endView = endValues.view;
if (DBG) {
View startView = (startValues != null) ? startValues.view : null;
Log.d(LOG_TAG, "Fade.onAppear: startView, startVis, endView, endVis = " +
- startView + ", " + startVisibility + ", " + endView + ", " + endVisibility);
+ startView + ", " + view);
}
- endView.setTransitionAlpha(0);
- TransitionListener transitionListener = new TransitionListenerAdapter() {
- boolean mCanceled = false;
- float mPausedAlpha;
-
- @Override
- public void onTransitionCancel(Transition transition) {
- endView.setTransitionAlpha(1);
- mCanceled = true;
- }
-
- @Override
- public void onTransitionEnd(Transition transition) {
- if (!mCanceled) {
- endView.setTransitionAlpha(1);
- }
- }
-
- @Override
- public void onTransitionPause(Transition transition) {
- mPausedAlpha = endView.getTransitionAlpha();
- endView.setTransitionAlpha(1);
- }
-
- @Override
- public void onTransitionResume(Transition transition) {
- endView.setTransitionAlpha(mPausedAlpha);
- }
- };
- addListener(transitionListener);
- return createAnimation(endView, 0, 1, null);
+ return createAnimation(view, 0, 1);
}
@Override
- public Animator onDisappear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
+ public Animator onDisappear(ViewGroup sceneRoot, final View view, TransitionValues startValues,
+ TransitionValues endValues) {
if ((mFadingMode & OUT) != OUT) {
return null;
}
- View view = null;
- View startView = (startValues != null) ? startValues.view : null;
- View endView = (endValues != null) ? endValues.view : null;
- if (DBG) {
- Log.d(LOG_TAG, "Fade.onDisappear: startView, startVis, endView, endVis = " +
- startView + ", " + startVisibility + ", " + endView + ", " + endVisibility);
- }
- View overlayView = null;
- View viewToKeep = null;
- if (endView == null || endView.getParent() == null) {
- if (endView != null) {
- // endView was removed from its parent - add it to the overlay
- view = overlayView = endView;
- } else if (startView != null) {
- // endView does not exist. Use startView only under certain
- // conditions, because placing a view in an overlay necessitates
- // it being removed from its current parent
- if (startView.getParent() == null) {
- // no parent - safe to use
- view = overlayView = startView;
- } else if (startView.getParent() instanceof View &&
- startView.getParent().getParent() == null) {
- View startParent = (View) startView.getParent();
- int id = startParent.getId();
- if (id != View.NO_ID && sceneRoot.findViewById(id) != null && mCanRemoveViews) {
- // no parent, but its parent is unparented but the parent
- // hierarchy has been replaced by a new hierarchy with the same id
- // and it is safe to un-parent startView
- view = overlayView = startView;
- }
- }
- }
- } else {
- // visibility change
- if (endVisibility == View.INVISIBLE) {
- view = endView;
- viewToKeep = view;
- } else {
- // Becoming GONE
- if (startView == endView) {
- view = endView;
- viewToKeep = view;
- } else {
- view = startView;
- overlayView = view;
- }
- }
- }
- final int finalVisibility = endVisibility;
- // TODO: add automatic facility to Visibility superclass for keeping views around
- if (overlayView != null) {
- // TODO: Need to do this for general case of adding to overlay
- int screenX = (Integer) startValues.values.get(PROPNAME_SCREEN_X);
- int screenY = (Integer) startValues.values.get(PROPNAME_SCREEN_Y);
- int[] loc = new int[2];
- sceneRoot.getLocationOnScreen(loc);
- overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
- overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
- sceneRoot.getOverlay().add(overlayView);
- // TODO: add automatic facility to Visibility superclass for keeping views around
- final float startAlpha = 1;
- float endAlpha = 0;
- final View finalView = view;
- final View finalOverlayView = overlayView;
- final View finalViewToKeep = viewToKeep;
- final ViewGroup finalSceneRoot = sceneRoot;
- final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- finalView.setTransitionAlpha(startAlpha);
- // TODO: restore view offset from overlay repositioning
- if (finalViewToKeep != null) {
- finalViewToKeep.setVisibility(finalVisibility);
- }
- if (finalOverlayView != null) {
- finalSceneRoot.getOverlay().remove(finalOverlayView);
- }
- }
- @Override
- public void onAnimationPause(Animator animation) {
- if (finalOverlayView != null) {
- finalSceneRoot.getOverlay().remove(finalOverlayView);
- }
- }
+ return createAnimation(view, 1, 0);
+ }
+
+ private static class FadeAnimatorListener extends AnimatorListenerAdapter {
+ private final View mView;
+ private final float mEndAlpha;
+ private boolean mCanceled = false;
+ private float mPausedAlpha;
- @Override
- public void onAnimationResume(Animator animation) {
- if (finalOverlayView != null) {
- finalSceneRoot.getOverlay().add(finalOverlayView);
- }
- }
- };
- return createAnimation(view, startAlpha, endAlpha, endListener);
+ public FadeAnimatorListener(View view, float endAlpha) {
+ mView = view;
+ mEndAlpha = endAlpha;
}
- if (viewToKeep != null) {
- // TODO: find a different way to do this, like just changing the view to be
- // VISIBLE for the duration of the transition
- viewToKeep.setVisibility((View.VISIBLE));
- // TODO: add automatic facility to Visibility superclass for keeping views around
- final float startAlpha = 1;
- float endAlpha = 0;
- final View finalView = view;
- final View finalOverlayView = overlayView;
- final View finalViewToKeep = viewToKeep;
- final ViewGroup finalSceneRoot = sceneRoot;
- final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
- boolean mCanceled = false;
- float mPausedAlpha = -1;
- @Override
- public void onAnimationPause(Animator animation) {
- if (finalViewToKeep != null && !mCanceled) {
- finalViewToKeep.setVisibility(finalVisibility);
- }
- mPausedAlpha = finalView.getTransitionAlpha();
- finalView.setTransitionAlpha(startAlpha);
- }
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ mCanceled = true;
+ if (mPausedAlpha >= 0) {
+ mView.setTransitionAlpha(mPausedAlpha);
+ }
+ }
- @Override
- public void onAnimationResume(Animator animation) {
- if (finalViewToKeep != null && !mCanceled) {
- finalViewToKeep.setVisibility(View.VISIBLE);
- }
- finalView.setTransitionAlpha(mPausedAlpha);
- }
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ if (!mCanceled) {
+ mView.setTransitionAlpha(mEndAlpha);
+ }
+ }
- @Override
- public void onAnimationCancel(Animator animation) {
- mCanceled = true;
- if (mPausedAlpha >= 0) {
- finalView.setTransitionAlpha(mPausedAlpha);
- }
- }
+ @Override
+ public void onAnimationPause(Animator animator) {
+ mPausedAlpha = mView.getTransitionAlpha();
+ mView.setTransitionAlpha(mEndAlpha);
+ }
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!mCanceled) {
- finalView.setTransitionAlpha(startAlpha);
- }
- // TODO: restore view offset from overlay repositioning
- if (finalViewToKeep != null && !mCanceled) {
- finalViewToKeep.setVisibility(finalVisibility);
- }
- if (finalOverlayView != null) {
- finalSceneRoot.getOverlay().remove(finalOverlayView);
- }
- }
- };
- return createAnimation(view, startAlpha, endAlpha, endListener);
+ @Override
+ public void onAnimationResume(Animator animator) {
+ mView.setTransitionAlpha(mPausedAlpha);
}
- return null;
}
-
-} \ No newline at end of file
+}
diff --git a/core/java/android/transition/MatrixClippedDrawable.java b/core/java/android/transition/MatrixClippedDrawable.java
new file mode 100644
index 000000000000..ebaad59d134c
--- /dev/null
+++ b/core/java/android/transition/MatrixClippedDrawable.java
@@ -0,0 +1,300 @@
+/*
+ * 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.transition;
+
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.Property;
+
+/**
+ * Used in MoveImage to mock an ImageView as a Drawable to be scaled in the scene root Overlay.
+ * @hide
+ */
+class MatrixClippedDrawable extends Drawable implements Drawable.Callback {
+ private static final String TAG = "MatrixClippedDrawable";
+
+ private ClippedMatrixState mClippedMatrixState;
+
+ public static final Property<MatrixClippedDrawable, Rect> CLIP_PROPERTY
+ = new Property<MatrixClippedDrawable, Rect>(Rect.class, "clipRect") {
+
+ @Override
+ public Rect get(MatrixClippedDrawable object) {
+ return object.getClipRect();
+ }
+
+ @Override
+ public void set(MatrixClippedDrawable object, Rect value) {
+ object.setClipRect(value);
+ }
+ };
+
+ public static final Property<MatrixClippedDrawable, Matrix> MATRIX_PROPERTY
+ = new Property<MatrixClippedDrawable, Matrix>(Matrix.class, "matrix") {
+ @Override
+ public void set(MatrixClippedDrawable object, Matrix value) {
+ object.setMatrix(value);
+ }
+
+ @Override
+ public Matrix get(MatrixClippedDrawable object) {
+ return object.getMatrix();
+ }
+ };
+
+ public MatrixClippedDrawable(Drawable drawable) {
+ this(null, null);
+
+ mClippedMatrixState.mDrawable = drawable;
+
+ if (drawable != null) {
+ drawable.setCallback(this);
+ }
+ }
+
+ public void setMatrix(Matrix matrix) {
+ if (matrix == null) {
+ mClippedMatrixState.mMatrix = null;
+ } else {
+ if (mClippedMatrixState.mMatrix == null) {
+ mClippedMatrixState.mMatrix = new Matrix();
+ }
+ mClippedMatrixState.mMatrix.set(matrix);
+ }
+ invalidateSelf();
+ }
+
+ public Matrix getMatrix() {
+ return mClippedMatrixState.mMatrix;
+ }
+
+ public Rect getClipRect() {
+ return mClippedMatrixState.mClipRect;
+ }
+
+ public void setClipRect(Rect clipRect) {
+ if (clipRect == null) {
+ if (mClippedMatrixState.mClipRect != null) {
+ mClippedMatrixState.mClipRect = null;
+ invalidateSelf();
+ }
+ } else {
+ if (mClippedMatrixState.mClipRect == null) {
+ mClippedMatrixState.mClipRect = new Rect(clipRect);
+ } else {
+ mClippedMatrixState.mClipRect.set(clipRect);
+ }
+ invalidateSelf();
+ }
+ }
+
+ // overrides from Drawable.Callback
+
+ public void invalidateDrawable(Drawable who) {
+ final Drawable.Callback callback = getCallback();
+ if (callback != null) {
+ callback.invalidateDrawable(this);
+ }
+ }
+
+ public void scheduleDrawable(Drawable who, Runnable what, long when) {
+ final Drawable.Callback callback = getCallback();
+ if (callback != null) {
+ callback.scheduleDrawable(this, what, when);
+ }
+ }
+
+ public void unscheduleDrawable(Drawable who, Runnable what) {
+ final Drawable.Callback callback = getCallback();
+ if (callback != null) {
+ callback.unscheduleDrawable(this, what);
+ }
+ }
+
+ // overrides from Drawable
+
+ @Override
+ public int getChangingConfigurations() {
+ return super.getChangingConfigurations()
+ | mClippedMatrixState.mChangingConfigurations
+ | mClippedMatrixState.mDrawable.getChangingConfigurations();
+ }
+
+ @Override
+ public boolean getPadding(Rect padding) {
+ // XXX need to adjust padding!
+ return mClippedMatrixState.mDrawable.getPadding(padding);
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ mClippedMatrixState.mDrawable.setVisible(visible, restart);
+ return super.setVisible(visible, restart);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mClippedMatrixState.mDrawable.setAlpha(alpha);
+ }
+
+ @Override
+ public int getAlpha() {
+ return mClippedMatrixState.mDrawable.getAlpha();
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ mClippedMatrixState.mDrawable.setColorFilter(cf);
+ }
+
+ @Override
+ public int getOpacity() {
+ return mClippedMatrixState.mDrawable.getOpacity();
+ }
+
+ @Override
+ public boolean isStateful() {
+ return mClippedMatrixState.mDrawable.isStateful();
+ }
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ return mClippedMatrixState.mDrawable.setState(state);
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ mClippedMatrixState.mDrawable.setLevel(level);
+ invalidateSelf();
+ return true;
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ super.setBounds(bounds);
+ if (mClippedMatrixState.mMatrix == null) {
+ mClippedMatrixState.mDrawable.setBounds(bounds);
+ } else {
+ int drawableWidth = mClippedMatrixState.mDrawable.getIntrinsicWidth();
+ int drawableHeight = mClippedMatrixState.mDrawable.getIntrinsicHeight();
+ mClippedMatrixState.mDrawable.setBounds(bounds.left, bounds.top,
+ drawableWidth + bounds.left, drawableHeight + bounds.top);
+ }
+ invalidateSelf();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ Rect bounds = getBounds();
+ int left = bounds.left;
+ int top = bounds.top;
+ int saveCount = canvas.getSaveCount();
+ canvas.save();
+ if (mClippedMatrixState.mClipRect != null) {
+ canvas.clipRect(mClippedMatrixState.mClipRect);
+ } else {
+ canvas.clipRect(bounds);
+ }
+
+ if (mClippedMatrixState != null && !mClippedMatrixState.mMatrix.isIdentity()) {
+ canvas.translate(left, top);
+ canvas.concat(mClippedMatrixState.mMatrix);
+ canvas.translate(-left, -top);
+ }
+ mClippedMatrixState.mDrawable.draw(canvas);
+ canvas.restoreToCount(saveCount);
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mClippedMatrixState.mDrawable.getIntrinsicWidth();
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mClippedMatrixState.mDrawable.getIntrinsicHeight();
+ }
+
+ @Override
+ public Drawable.ConstantState getConstantState() {
+ if (mClippedMatrixState.canConstantState()) {
+ mClippedMatrixState.mChangingConfigurations = getChangingConfigurations();
+ return mClippedMatrixState;
+ }
+ return null;
+ }
+
+ final static class ClippedMatrixState extends Drawable.ConstantState {
+ Drawable mDrawable;
+ Matrix mMatrix;
+ Rect mClipRect;
+
+ private boolean mCheckedConstantState;
+ private boolean mCanConstantState;
+ int mChangingConfigurations;
+
+ ClippedMatrixState(ClippedMatrixState orig, MatrixClippedDrawable owner, Resources res) {
+ if (orig != null) {
+ if (res != null) {
+ mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
+ } else {
+ mDrawable = orig.mDrawable.getConstantState().newDrawable();
+ }
+ mDrawable.setCallback(owner);
+ mCheckedConstantState = mCanConstantState = true;
+ if (orig.mMatrix != null) {
+ mMatrix = new Matrix(orig.mMatrix);
+ }
+ if (orig.mClipRect != null) {
+ mClipRect = new Rect(orig.mClipRect);
+ }
+ }
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new MatrixClippedDrawable(this, null);
+ }
+
+ @Override
+ public Drawable newDrawable(Resources res) {
+ return new MatrixClippedDrawable(this, res);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return mChangingConfigurations;
+ }
+
+ boolean canConstantState() {
+ if (!mCheckedConstantState) {
+ mCanConstantState = mDrawable.getConstantState() != null;
+ mCheckedConstantState = true;
+ }
+
+ return mCanConstantState;
+ }
+ }
+
+ private MatrixClippedDrawable(ClippedMatrixState state, Resources res) {
+ mClippedMatrixState = new ClippedMatrixState(state, this, res);
+ }
+
+}
diff --git a/core/java/android/transition/MoveImage.java b/core/java/android/transition/MoveImage.java
new file mode 100644
index 000000000000..d68e97190a36
--- /dev/null
+++ b/core/java/android/transition/MoveImage.java
@@ -0,0 +1,326 @@
+/*
+ * 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.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.RectEvaluator;
+import android.animation.TypeEvaluator;
+import android.animation.ValueAnimator;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroupOverlay;
+import android.view.ViewParent;
+import android.widget.ImageView;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ * Transitions ImageViews, including size, scaleType, and matrix. The ImageView drawable
+ * must remain the same between both start and end states, but the
+ * {@link ImageView#setScaleType(android.widget.ImageView.ScaleType)} may
+ * differ.
+ */
+public class MoveImage extends Transition {
+ private static final String TAG = "MoveImage";
+ private static final String PROPNAME_MATRIX = "android:moveImage:matrix";
+ private static final String PROPNAME_BOUNDS = "android:moveImage:bounds";
+ private static final String PROPNAME_CLIP = "android:moveImage:clip";
+ private static final String PROPNAME_DRAWABLE = "android:moveImage:drawable";
+
+ private int[] mTempLoc = new int[2];
+
+ private static final String[] sTransitionProperties = {
+ PROPNAME_MATRIX,
+ PROPNAME_BOUNDS,
+ PROPNAME_CLIP,
+ PROPNAME_DRAWABLE,
+ };
+
+ private void captureValues(TransitionValues transitionValues) {
+ View view = transitionValues.view;
+ if (!(view instanceof ImageView) || view.getVisibility() != View.VISIBLE) {
+ return;
+ }
+ Map<String, Object> values = transitionValues.values;
+
+ ViewGroup parent = (ViewGroup) view.getParent();
+ parent.getLocationInWindow(mTempLoc);
+ int paddingLeft = view.getPaddingLeft();
+ int paddingTop = view.getPaddingTop();
+ int paddingRight = view.getPaddingRight();
+ int paddingBottom = view.getPaddingBottom();
+ int left = mTempLoc[0] + paddingLeft + view.getLeft() + Math.round(view.getTranslationX());
+ int top = mTempLoc[1] + paddingTop + view.getTop() + Math.round(view.getTranslationY());
+ int right = left + view.getWidth() - paddingRight - paddingLeft;
+ int bottom = top + view.getHeight() - paddingTop - paddingBottom;
+
+ Rect bounds = new Rect(left, top, right, bottom);
+ values.put(PROPNAME_BOUNDS, bounds);
+ ImageView imageView = (ImageView) view;
+ Matrix matrix = getMatrix(imageView);
+ values.put(PROPNAME_MATRIX, matrix);
+ values.put(PROPNAME_CLIP, findClip(imageView));
+ values.put(PROPNAME_DRAWABLE, imageView.getDrawable());
+ }
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ captureValues(transitionValues);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ captureValues(transitionValues);
+ }
+
+ @Override
+ public String[] getTransitionProperties() {
+ return sTransitionProperties;
+ }
+
+ /**
+ * Creates an Animator for ImageViews moving, changing dimensions, and/or changing
+ * {@link android.widget.ImageView.ScaleType}.
+ * @param sceneRoot The root of the transition hierarchy.
+ * @param startValues The values for a specific target in the start scene.
+ * @param endValues The values for the target in the end scene.
+ * @return An Animator to move an ImageView or null if the View is not an ImageView,
+ * the Drawable changed, the View is not VISIBLE, or there was no change.
+ */
+ @Override
+ public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+ TransitionValues endValues) {
+ if (startValues == null || endValues == null
+ || startValues.values.get(PROPNAME_BOUNDS) == null
+ || endValues.values.get(PROPNAME_BOUNDS) == null
+ || startValues.values.get(PROPNAME_DRAWABLE)
+ != endValues.values.get(PROPNAME_DRAWABLE)) {
+ return null;
+ }
+ ArrayList<PropertyValuesHolder> changes = new ArrayList<PropertyValuesHolder>();
+
+ Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
+ Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
+
+ if (!startMatrix.equals(endMatrix)) {
+ changes.add(PropertyValuesHolder.ofObject(MatrixClippedDrawable.MATRIX_PROPERTY,
+ new MatrixEvaluator(), startMatrix, endMatrix));
+ }
+
+ sceneRoot.getLocationInWindow(mTempLoc);
+ int rootX = mTempLoc[0];
+ int rootY = mTempLoc[1];
+ final ImageView imageView = (ImageView) endValues.view;
+
+ Drawable drawable = imageView.getDrawable();
+
+ Rect startBounds = new Rect((Rect) startValues.values.get(PROPNAME_BOUNDS));
+ Rect endBounds = new Rect((Rect) endValues.values.get(PROPNAME_BOUNDS));
+ startBounds.offset(-rootX, -rootY);
+ endBounds.offset(-rootX, -rootY);
+
+ if (!startBounds.equals(endBounds)) {
+ changes.add(PropertyValuesHolder.ofObject("bounds", new RectEvaluator(new Rect()),
+ startBounds, endBounds));
+ }
+
+ Rect startClip = (Rect) startValues.values.get(PROPNAME_CLIP);
+ Rect endClip = (Rect) endValues.values.get(PROPNAME_CLIP);
+ if (startClip != null || endClip != null) {
+ startClip = nonNullClip(startClip, sceneRoot, rootX, rootY);
+ endClip = nonNullClip(endClip, sceneRoot, rootX, rootY);
+
+ expandClip(startBounds, startMatrix, startClip, endClip);
+ expandClip(endBounds, endMatrix, endClip, startClip);
+ boolean clipped = !startClip.contains(startBounds) || !endClip.contains(endBounds);
+ if (!clipped) {
+ startClip = null;
+ } else if (!startClip.equals(endClip)) {
+ changes.add(PropertyValuesHolder.ofObject(MatrixClippedDrawable.CLIP_PROPERTY,
+ new RectEvaluator(), startClip, endClip));
+ }
+ }
+
+ if (changes.isEmpty()) {
+ return null;
+ }
+
+ drawable = drawable.getConstantState().newDrawable();
+ final MatrixClippedDrawable matrixClippedDrawable = new MatrixClippedDrawable(drawable);
+ matrixClippedDrawable.setMatrix(startMatrix);
+ matrixClippedDrawable.setBounds(startBounds);
+ matrixClippedDrawable.setClipRect(startClip);
+
+ imageView.setVisibility(View.INVISIBLE);
+ final ViewGroupOverlay overlay = sceneRoot.getOverlay();
+ overlay.add(matrixClippedDrawable);
+ ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(matrixClippedDrawable,
+ changes.toArray(new PropertyValuesHolder[changes.size()]));
+
+ AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ imageView.setVisibility(View.VISIBLE);
+ overlay.remove(matrixClippedDrawable);
+ }
+
+ @Override
+ public void onAnimationPause(Animator animation) {
+ imageView.setVisibility(View.VISIBLE);
+ overlay.remove(matrixClippedDrawable);
+ }
+
+ @Override
+ public void onAnimationResume(Animator animation) {
+ imageView.setVisibility(View.INVISIBLE);
+ overlay.add(matrixClippedDrawable);
+ }
+ };
+
+ animator.addListener(listener);
+ animator.addPauseListener(listener);
+
+ return animator;
+ }
+
+ private static Rect nonNullClip(Rect clip, ViewGroup sceneRoot, int rootX, int rootY) {
+ if (clip != null) {
+ clip = new Rect(clip);
+ clip.offset(-rootX, -rootY);
+ } else {
+ clip = new Rect(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight());
+ }
+ return clip;
+ }
+
+ private static void expandClip(Rect bounds, Matrix matrix, Rect clip, Rect otherClip) {
+ RectF boundsF = new RectF(bounds);
+ matrix.mapRect(boundsF);
+ clip.left = expandMinDimension(boundsF.left, clip.left, otherClip.left);
+ clip.top = expandMinDimension(boundsF.top, clip.top, otherClip.top);
+ clip.right = expandMaxDimension(boundsF.right, clip.right, otherClip.right);
+ clip.bottom = expandMaxDimension(boundsF.bottom, clip.bottom, otherClip.bottom);
+ }
+
+ private static int expandMinDimension(float boundsDimension, int clipDimension,
+ int otherClipDimension) {
+ if (clipDimension > boundsDimension) {
+ // Already clipped in that dimension, return the clipped value
+ return clipDimension;
+ }
+ return Math.min(clipDimension, otherClipDimension);
+ }
+
+ private static int expandMaxDimension(float boundsDimension, int clipDimension,
+ int otherClipDimension) {
+ return -expandMinDimension(-boundsDimension, -clipDimension, -otherClipDimension);
+ }
+
+ private static Matrix getMatrix(ImageView imageView) {
+ Drawable drawable = imageView.getDrawable();
+ int drawableWidth = drawable.getIntrinsicWidth();
+ int drawableHeight = drawable.getIntrinsicHeight();
+ ImageView.ScaleType scaleType = imageView.getScaleType();
+ if (drawableWidth <= 0 || drawableHeight <= 0 || scaleType == ImageView.ScaleType.FIT_XY) {
+ return null;
+ }
+ return new Matrix(imageView.getImageMatrix());
+ }
+
+ private Rect findClip(ImageView imageView) {
+ if (imageView.getCropToPadding()) {
+ Rect clip = getClip(imageView);
+ clip.left += imageView.getPaddingLeft();
+ clip.right -= imageView.getPaddingRight();
+ clip.top += imageView.getPaddingTop();
+ clip.bottom -= imageView.getPaddingBottom();
+ return clip;
+ } else {
+ View view = imageView;
+ ViewParent viewParent;
+ while ((viewParent = view.getParent()) instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) viewParent;
+ if (viewGroup.getClipChildren()) {
+ Rect clip = getClip(view);
+ return clip;
+ }
+ view = viewGroup;
+ }
+ }
+ return null;
+ }
+
+ private Rect getClip(View clipView) {
+ Rect clipBounds = clipView.getClipBounds();
+ if (clipBounds == null) {
+ clipBounds = new Rect(clipView.getLeft(), clipView.getTop(),
+ clipView.getRight(), clipView.getBottom());
+ }
+
+ ViewParent parent = clipView.getParent();
+ if (parent instanceof ViewGroup) {
+ ViewGroup parentViewGroup = (ViewGroup) parent;
+ parentViewGroup.getLocationInWindow(mTempLoc);
+ clipBounds.offset(mTempLoc[0], mTempLoc[1]);
+ }
+
+ return clipBounds;
+ }
+
+ @Override
+ public Transition clone() {
+ MoveImage clone = (MoveImage) super.clone();
+ clone.mTempLoc = new int[2];
+ return clone;
+ }
+
+ private static class MatrixEvaluator implements TypeEvaluator<Matrix> {
+ static final Matrix sIdentity = new Matrix();
+ float[] mTempStartValues = new float[9];
+ float[] mTempEndValues = new float[9];
+ Matrix mTempMatrix = new Matrix();
+
+ @Override
+ public Matrix evaluate(float fraction, Matrix startValue, Matrix endValue) {
+ if (startValue == null && endValue == null) {
+ return null;
+ }
+ if (startValue == null) {
+ startValue = sIdentity;
+ } else if (endValue == null) {
+ endValue = sIdentity;
+ }
+ startValue.getValues(mTempStartValues);
+ endValue.getValues(mTempEndValues);
+ for (int i = 0; i < 9; i++) {
+ float diff = mTempEndValues[i] - mTempStartValues[i];
+ mTempEndValues[i] = mTempStartValues[i] + (fraction * diff);
+ }
+ mTempMatrix.setValues(mTempEndValues);
+ return mTempMatrix;
+ }
+ }
+}
diff --git a/core/java/android/transition/SidePropagation.java b/core/java/android/transition/SidePropagation.java
new file mode 100644
index 000000000000..c331945b27ca
--- /dev/null
+++ b/core/java/android/transition/SidePropagation.java
@@ -0,0 +1,165 @@
+/*
+ * 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.transition;
+
+import android.graphics.Rect;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * A <code>TransitionPropagation</code> that propagates based on the distance to the side
+ * and, orthogonally, the distance to epicenter. If the transitioning View is visible in
+ * the start of the transition, then it will transition sooner when closer to the side and
+ * later when farther. If the view is not visible in the start of the transition, then
+ * it will transition later when closer to the side and sooner when farther from the edge.
+ * This is the default TransitionPropagation used with {@link android.transition.Slide}.
+ */
+public class SidePropagation extends VisibilityPropagation {
+ private static final String TAG = "SlidePropagation";
+
+ /**
+ * Transition propagates relative to the distance of the left side of the scene.
+ */
+ public static final int LEFT = Slide.LEFT;
+
+ /**
+ * Transition propagates relative to the distance of the top of the scene.
+ */
+ public static final int TOP = Slide.TOP;
+
+ /**
+ * Transition propagates relative to the distance of the right side of the scene.
+ */
+ public static final int RIGHT = Slide.RIGHT;
+
+ /**
+ * Transition propagates relative to the distance of the bottom of the scene.
+ */
+ public static final int BOTTOM = Slide.BOTTOM;
+
+ private float mPropagationSpeed = 4.0f;
+ private int mSide = BOTTOM;
+
+ /**
+ * Sets the side that is used to calculate the transition propagation. If the transitioning
+ * View is visible in the start of the transition, then it will transition sooner when
+ * closer to the side and later when farther. If the view is not visible in the start of
+ * the transition, then it will transition later when closer to the side and sooner when
+ * farther from the edge. The default is {@link #BOTTOM}.
+ *
+ * @param side The side that is used to calculate the transition propagation. Must be one of
+ * {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, or {@link #BOTTOM}.
+ */
+ public void setSide(int side) {
+ mSide = side;
+ }
+
+ /**
+ * Sets the speed at which transition propagation happens, relative to the duration of the
+ * Transition. A <code>propagationSpeed</code> of 1 means that a View centered at the side
+ * set in {@link #setSide(int)} and View centered at the opposite edge will have a difference
+ * in start delay of approximately the duration of the Transition. A speed of 2 means the
+ * start delay difference will be approximately half of the duration of the transition. A
+ * value of 0 is illegal, but negative values will invert the propagation.
+ *
+ * @param propagationSpeed The speed at which propagation occurs, relative to the duration
+ * of the transition. A speed of 4 means it works 4 times as fast
+ * as the duration of the transition. May not be 0.
+ */
+ public void setPropagationSpeed(float propagationSpeed) {
+ if (propagationSpeed == 0) {
+ throw new IllegalArgumentException("propagationSpeed may not be 0");
+ }
+ mPropagationSpeed = propagationSpeed;
+ }
+
+ @Override
+ public long getStartDelay(ViewGroup sceneRoot, Transition transition,
+ TransitionValues startValues, TransitionValues endValues) {
+ if (startValues == null && endValues == null) {
+ return 0;
+ }
+ int directionMultiplier = 1;
+ Rect epicenter = transition.getEpicenter();
+ TransitionValues positionValues;
+ if (endValues == null || getViewVisibility(startValues) == View.VISIBLE) {
+ positionValues = startValues;
+ directionMultiplier = -1;
+ } else {
+ positionValues = endValues;
+ }
+
+ int viewCenterX = getViewX(positionValues);
+ int viewCenterY = getViewY(positionValues);
+
+ int[] loc = new int[2];
+ sceneRoot.getLocationOnScreen(loc);
+ int left = loc[0] + Math.round(sceneRoot.getTranslationX());
+ int top = loc[1] + Math.round(sceneRoot.getTranslationY());
+ int right = left + sceneRoot.getWidth();
+ int bottom = top + sceneRoot.getHeight();
+
+ int epicenterX;
+ int epicenterY;
+ if (epicenter != null) {
+ epicenterX = epicenter.centerX();
+ epicenterY = epicenter.centerY();
+ } else {
+ epicenterX = (left + right) / 2;
+ epicenterY = (top + bottom) / 2;
+ }
+
+ float distance = distance(viewCenterX, viewCenterY, epicenterX, epicenterY,
+ left, top, right, bottom);
+ float maxDistance = getMaxDistance(sceneRoot);
+ float distanceFraction = distance/maxDistance;
+
+ return Math.round(transition.getDuration() * directionMultiplier / mPropagationSpeed
+ * distanceFraction);
+ }
+
+ private int distance(int viewX, int viewY, int epicenterX, int epicenterY,
+ int left, int top, int right, int bottom) {
+ int distance = 0;
+ switch (mSide) {
+ case LEFT:
+ distance = right - viewX + Math.abs(epicenterY - viewY);
+ break;
+ case TOP:
+ distance = bottom - viewY + Math.abs(epicenterX - viewX);
+ break;
+ case RIGHT:
+ distance = viewX - left + Math.abs(epicenterY - viewY);
+ break;
+ case BOTTOM:
+ distance = viewY - top + Math.abs(epicenterX - viewX);
+ break;
+ }
+ return distance;
+ }
+
+ private int getMaxDistance(ViewGroup sceneRoot) {
+ switch (mSide) {
+ case LEFT:
+ case RIGHT:
+ return sceneRoot.getWidth();
+ default:
+ return sceneRoot.getHeight();
+ }
+ }
+}
diff --git a/core/java/android/transition/Slide.java b/core/java/android/transition/Slide.java
index b38973ce122d..0ff8ddd4d1f9 100644
--- a/core/java/android/transition/Slide.java
+++ b/core/java/android/transition/Slide.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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,53 +13,240 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package android.transition;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.graphics.Rect;
+import android.util.Log;
+import android.util.Property;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
/**
- * This transition captures the visibility of target objects before and
- * after a scene change and animates any changes by sliding the target
- * objects into or out of place.
- *
- * @hide
+ * This transition tracks changes to the visibility of target views in the
+ * start and end scenes and moves views in or out from one of the edges of the
+ * scene. Visibility is determined by both the
+ * {@link View#setVisibility(int)} state of the view as well as whether it
+ * is parented in the current view hierarchy. Disappearing Views are
+ * limited as described in {@link Visibility#onDisappear(android.view.ViewGroup,
+ * TransitionValues, int, TransitionValues, int)}.
*/
public class Slide extends Visibility {
+ private static final String TAG = "Slide";
- // TODO: Add parameter for sliding factor - it's hard-coded below
+ /**
+ * Move Views in or out of the left edge of the scene.
+ * @see #setSlideEdge(int)
+ */
+ public static final int LEFT = 0;
- private static final TimeInterpolator sAccelerator = new AccelerateInterpolator();
- private static final TimeInterpolator sDecelerator = new DecelerateInterpolator();
+ /**
+ * Move Views in or out of the top edge of the scene.
+ * @see #setSlideEdge(int)
+ */
+ public static final int TOP = 1;
- @Override
- public Animator onAppear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
- View endView = (endValues != null) ? endValues.view : null;
- endView.setTranslationY(-2 * endView.getHeight());
- ObjectAnimator anim = ObjectAnimator.ofFloat(endView, View.TRANSLATION_Y,
- -2 * endView.getHeight(), 0);
- anim.setInterpolator(sDecelerator);
+ /**
+ * Move Views in or out of the right edge of the scene.
+ * @see #setSlideEdge(int)
+ */
+ public static final int RIGHT = 2;
+
+ /**
+ * Move Views in or out of the bottom edge of the scene. This is the
+ * default slide direction.
+ * @see #setSlideEdge(int)
+ */
+ public static final int BOTTOM = 3;
+
+ private static final TimeInterpolator sDecelerate = new DecelerateInterpolator();
+ private static final TimeInterpolator sAccelerate = new AccelerateInterpolator();
+
+ private int[] mTempLoc = new int[2];
+ private CalculateSlide mSlideCalculator = sCalculateBottom;
+
+ private interface CalculateSlide {
+ /** Returns the translation value for view when it out of the scene */
+ float getGone(ViewGroup sceneRoot, View view);
+
+ /** Returns the translation value for view when it is in the scene */
+ float getHere(View view);
+
+ /** Returns the property to animate translation */
+ Property<View, Float> getProperty();
+ }
+
+ private static abstract class CalculateSlideHorizontal implements CalculateSlide {
+ @Override
+ public float getHere(View view) {
+ return view.getTranslationX();
+ }
+
+ @Override
+ public Property<View, Float> getProperty() {
+ return View.TRANSLATION_X;
+ }
+ }
+
+ private static abstract class CalculateSlideVertical implements CalculateSlide {
+ @Override
+ public float getHere(View view) {
+ return view.getTranslationY();
+ }
+
+ @Override
+ public Property<View, Float> getProperty() {
+ return View.TRANSLATION_Y;
+ }
+ }
+
+ private static final CalculateSlide sCalculateLeft = new CalculateSlideHorizontal() {
+ @Override
+ public float getGone(ViewGroup sceneRoot, View view) {
+ return view.getTranslationX() - sceneRoot.getWidth();
+ }
+ };
+
+ private static final CalculateSlide sCalculateTop = new CalculateSlideVertical() {
+ @Override
+ public float getGone(ViewGroup sceneRoot, View view) {
+ return view.getTranslationY() - sceneRoot.getHeight();
+ }
+ };
+
+ private static final CalculateSlide sCalculateRight = new CalculateSlideHorizontal() {
+ @Override
+ public float getGone(ViewGroup sceneRoot, View view) {
+ return view.getTranslationX() + sceneRoot.getWidth();
+ }
+ };
+
+ private static final CalculateSlide sCalculateBottom = new CalculateSlideVertical() {
+ @Override
+ public float getGone(ViewGroup sceneRoot, View view) {
+ return view.getTranslationY() + sceneRoot.getHeight();
+ }
+ };
+
+ /**
+ * Constructor using the default {@link android.transition.Slide#BOTTOM}
+ * slide edge direction.
+ */
+ public Slide() {
+ setSlideEdge(BOTTOM);
+ }
+
+ /**
+ * Constructor using the provided slide edge direction.
+ */
+ public Slide(int slideEdge) {
+ setSlideEdge(slideEdge);
+ }
+
+ /**
+ * Change the edge that Views appear and disappear from.
+ * @param slideEdge The edge of the scene to use for Views appearing and disappearing.
+ */
+ public void setSlideEdge(int slideEdge) {
+ switch (slideEdge) {
+ case LEFT:
+ mSlideCalculator = sCalculateLeft;
+ break;
+ case TOP:
+ mSlideCalculator = sCalculateTop;
+ break;
+ case RIGHT:
+ mSlideCalculator = sCalculateRight;
+ break;
+ case BOTTOM:
+ mSlideCalculator = sCalculateBottom;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid slide direction");
+ }
+ SidePropagation propagation = new SidePropagation();
+ propagation.setSide(slideEdge);
+ setPropagation(propagation);
+ }
+
+ private Animator createAnimation(final View view, Property<View, Float> property,
+ float start, float end, float terminalValue, TimeInterpolator interpolator) {
+ view.setTranslationY(start);
+ if (start == end) {
+ return null;
+ }
+ final ObjectAnimator anim = ObjectAnimator.ofFloat(view, property, start, end);
+
+ SlideAnimatorListener listener = new SlideAnimatorListener(view, terminalValue, end);
+ anim.addListener(listener);
+ anim.addPauseListener(listener);
+ anim.setInterpolator(interpolator);
return anim;
}
@Override
- public Animator onDisappear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
- View startView = (startValues != null) ? startValues.view : null;
- startView.setTranslationY(0);
- ObjectAnimator anim = ObjectAnimator.ofFloat(startView, View.TRANSLATION_Y, 0,
- -2 * startView.getHeight());
- anim.setInterpolator(sAccelerator);
- return anim;
+ public Animator onAppear(ViewGroup sceneRoot, View view,
+ TransitionValues startValues, TransitionValues endValues) {
+ if (endValues == null) {
+ return null;
+ }
+ float end = mSlideCalculator.getHere(view);
+ float start = mSlideCalculator.getGone(sceneRoot, view);
+ return createAnimation(view, mSlideCalculator.getProperty(), start, end, end, sDecelerate);
}
+ @Override
+ public Animator onDisappear(ViewGroup sceneRoot, View view,
+ TransitionValues startValues, TransitionValues endValues) {
+ float start = mSlideCalculator.getHere(view);
+ float end = mSlideCalculator.getGone(sceneRoot, view);
+
+ return createAnimation(view, mSlideCalculator.getProperty(), start, end, start,
+ sAccelerate);
+ }
+
+ private static class SlideAnimatorListener extends AnimatorListenerAdapter {
+ private boolean mCanceled = false;
+ private float mPausedY;
+ private final View mView;
+ private final float mEndY;
+ private final float mTerminalY;
+
+ public SlideAnimatorListener(View view, float terminalY, float endY) {
+ mView = view;
+ mTerminalY = terminalY;
+ mEndY = endY;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ mView.setTranslationY(mTerminalY);
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ if (!mCanceled) {
+ mView.setTranslationY(mTerminalY);
+ }
+ }
+
+ @Override
+ public void onAnimationPause(Animator animator) {
+ mPausedY = mView.getTranslationY();
+ mView.setTranslationY(mEndY);
+ }
+
+ @Override
+ public void onAnimationResume(Animator animator) {
+ mView.setTranslationY(mPausedY);
+ }
+ }
}
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index c88b4c03c6e8..b7ae31e4e5fb 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -19,10 +19,12 @@ package android.transition;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
+import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.SparseArray;
+import android.util.SparseLongArray;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
@@ -60,10 +62,18 @@ import java.util.List;
* <p>Transitions can be declared in XML resource files inside the <code>res/transition</code>
* directory. Transition resources consist of a tag name for one of the Transition
* subclasses along with attributes to define some of the attributes of that transition.
- * For example, here is a minimal resource file that declares a {@link ChangeBounds} transition:</p>
+ * For example, here is a minimal resource file that declares a {@link ChangeBounds} transition:
*
* {@sample development/samples/ApiDemos/res/transition/changebounds.xml ChangeBounds}
*
+ * <p>{@link android.transition.Explode} transition:</p>
+ *
+ * {@sample development/samples/ApiDemos/res/transition/explode.xml Explode}
+ *
+ * <p>{@link android.transition.MoveImage} transition:</p>
+ *
+ * {@sample development/samples/ApiDemos/res/transition/move_image.xml MoveImage}
+ *
* <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
* the same defaults as their code-created equivalents. Here is a slightly more
@@ -87,7 +97,8 @@ import java.util.List;
*
* Further information on XML resource descriptions for transitions can be found for
* {@link android.R.styleable#Transition}, {@link android.R.styleable#TransitionSet},
- * {@link android.R.styleable#TransitionTarget}, and {@link android.R.styleable#Fade}.
+ * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade}, and
+ * {@link android.R.styleable#Slide}.
*
*/
public abstract class Transition implements Cloneable {
@@ -149,6 +160,13 @@ public abstract class Transition implements Cloneable {
// to be run in runAnimators()
ArrayList<Animator> mAnimators = new ArrayList<Animator>();
+ // The function for calculating the Animation start delay.
+ TransitionPropagation mPropagation;
+
+ // The rectangular region for Transitions like Explode and TransitionPropagations
+ // like CircularPropagation
+ EpicenterCallback mEpicenterCallback;
+
/**
* Constructs a Transition object with no target objects. A transition with
* no targets defaults to running on all target objects in the scene hierarchy
@@ -435,6 +453,9 @@ public abstract class Transition implements Cloneable {
endValuesList.add(end);
}
ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+ long minStartDelay = Long.MAX_VALUE;
+ int minAnimator = mAnimators.size();
+ SparseLongArray startDelays = new SparseLongArray();
for (int i = 0; i < startValuesList.size(); ++i) {
TransitionValues start = startValuesList.get(i);
TransitionValues end = endValuesList.get(i);
@@ -497,6 +518,12 @@ public abstract class Transition implements Cloneable {
view = (start != null) ? start.view : null;
}
if (animator != null) {
+ if (mPropagation != null) {
+ long delay = mPropagation
+ .getStartDelay(sceneRoot, this, start, end);
+ startDelays.put(mAnimators.size(), delay);
+ minStartDelay = Math.min(delay, minStartDelay);
+ }
AnimationInfo info = new AnimationInfo(view, getName(),
sceneRoot.getWindowId(), infoValues);
runningAnimators.put(animator, info);
@@ -506,6 +533,14 @@ public abstract class Transition implements Cloneable {
}
}
}
+ if (minStartDelay != 0) {
+ for (int i = 0; i < startDelays.size(); i++) {
+ int index = startDelays.keyAt(i);
+ Animator animator = mAnimators.get(index);
+ long delay = startDelays.valueAt(i) - minStartDelay + animator.getStartDelay();
+ animator.setStartDelay(delay);
+ }
+ }
}
/**
@@ -565,7 +600,7 @@ public abstract class Transition implements Cloneable {
/**
* This is called internally once all animations have been set up by the
- * transition hierarchy. \
+ * transition hierarchy.
*
* @hide
*/
@@ -1010,6 +1045,7 @@ public abstract class Transition implements Cloneable {
} else {
captureEndValues(values);
}
+ capturePropagationValues(values);
if (start) {
mStartValues.viewValues.put(view, values);
if (id >= 0) {
@@ -1035,6 +1071,7 @@ public abstract class Transition implements Cloneable {
} else {
captureEndValues(values);
}
+ capturePropagationValues(values);
if (start) {
mStartValues.viewValues.put(view, values);
} else {
@@ -1122,6 +1159,7 @@ public abstract class Transition implements Cloneable {
} else {
captureEndValues(values);
}
+ capturePropagationValues(values);
if (start) {
if (!isListViewItem) {
mStartValues.viewValues.put(view, values);
@@ -1340,7 +1378,7 @@ public abstract class Transition implements Cloneable {
animator.setDuration(getDuration());
}
if (getStartDelay() >= 0) {
- animator.setStartDelay(getStartDelay());
+ animator.setStartDelay(getStartDelay() + animator.getStartDelay());
}
if (getInterpolator() != null) {
animator.setInterpolator(getInterpolator());
@@ -1473,6 +1511,98 @@ public abstract class Transition implements Cloneable {
return this;
}
+ /**
+ * Sets the callback to use to find the epicenter of a Transition. A null value indicates
+ * that there is no epicenter in the Transition and getEpicenter() will return null.
+ * Transitions like {@link android.transition.Explode} use a point or Rect to orient
+ * the direction of travel. This is called the epicenter of the Transition and is
+ * typically centered on a touched View. The
+ * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
+ * dynamically retrieve the epicenter during a Transition.
+ * @param epicenterCallback The callback to use to find the epicenter of the Transition.
+ */
+ public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
+ mEpicenterCallback = epicenterCallback;
+ }
+
+ /**
+ * Returns the callback used to find the epicenter of the Transition.
+ * Transitions like {@link android.transition.Explode} use a point or Rect to orient
+ * the direction of travel. This is called the epicenter of the Transition and is
+ * typically centered on a touched View. The
+ * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
+ * dynamically retrieve the epicenter during a Transition.
+ * @return the callback used to find the epicenter of the Transition.
+ */
+ public EpicenterCallback getEpicenterCallback() {
+ return mEpicenterCallback;
+ }
+
+ /**
+ * Returns the epicenter as specified by the
+ * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
+ * @return the epicenter as specified by the
+ * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
+ * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
+ */
+ public Rect getEpicenter() {
+ if (mEpicenterCallback == null) {
+ return null;
+ }
+ return mEpicenterCallback.getEpicenter(this);
+ }
+
+ /**
+ * Sets the method for determining Animator start delays.
+ * When a Transition affects several Views like {@link android.transition.Explode} or
+ * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
+ * such that the Animator start delay depends on position of the View. The
+ * TransitionPropagation specifies how the start delays are calculated.
+ * @param transitionPropagation The class used to determine the start delay of
+ * Animators created by this Transition. A null value
+ * indicates that no delay should be used.
+ */
+ public void setPropagation(TransitionPropagation transitionPropagation) {
+ mPropagation = transitionPropagation;
+ }
+
+ /**
+ * Returns the {@link android.transition.TransitionPropagation} used to calculate Animator start
+ * delays.
+ * When a Transition affects several Views like {@link android.transition.Explode} or
+ * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
+ * such that the Animator start delay depends on position of the View. The
+ * TransitionPropagation specifies how the start delays are calculated.
+ * @return the {@link android.transition.TransitionPropagation} used to calculate Animator start
+ * delays. This is null by default.
+ */
+ public TransitionPropagation getPropagation() {
+ return mPropagation;
+ }
+
+ /**
+ * Captures TransitionPropagation values for the given view and the
+ * hierarchy underneath it.
+ */
+ void capturePropagationValues(TransitionValues transitionValues) {
+ if (mPropagation != null) {
+ String[] propertyNames = mPropagation.getPropagationProperties();
+ if (propertyNames == null) {
+ return;
+ }
+ boolean containsAll = true;
+ for (int i = 0; i < propertyNames.length; i++) {
+ if (!transitionValues.values.containsKey(propertyNames[i])) {
+ containsAll = false;
+ break;
+ }
+ }
+ if (!containsAll) {
+ mPropagation.captureValues(transitionValues);
+ }
+ }
+ }
+
Transition setSceneRoot(ViewGroup sceneRoot) {
mSceneRoot = sceneRoot;
return this;
@@ -1710,4 +1840,28 @@ public abstract class Transition implements Cloneable {
}
}
+ /**
+ * Class to get the epicenter of Transition. Use
+ * {@link #setEpicenterCallback(android.transition.Transition.EpicenterCallback)} to
+ * set the callback used to calculate the epicenter of the Transition. Override
+ * {@link #getEpicenter()} to return the rectangular region in screen coordinates of
+ * the epicenter of the transition.
+ * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
+ */
+ public static abstract class EpicenterCallback {
+
+ /**
+ * Implementers must override to return the epicenter of the Transition in screen
+ * coordinates. Transitions like {@link android.transition.Explode} depend upon
+ * an epicenter for the Transition. In Explode, Views move toward or away from the
+ * center of the epicenter Rect along the vector between the epicenter and the center
+ * of the View appearing and disappearing. Some Transitions, such as
+ * {@link android.transition.Fade} pay no attention to the epicenter.
+ *
+ * @param transition The transition for which the epicenter applies.
+ * @return The Rect region of the epicenter of <code>transition</code> or null if
+ * there is no epicenter.
+ */
+ public abstract Rect getEpicenter(Transition transition);
+ }
}
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 912f2ed88962..f675c6a3f1ae 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
-import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.InflateException;
@@ -146,7 +145,13 @@ public class TransitionInflater {
transition = new ChangeBounds();
newTransition = true;
} else if ("slide".equals(name)) {
- transition = new Slide();
+ transition = createSlideTransition(attrs);
+ newTransition = true;
+ } else if ("explode".equals(name)) {
+ transition = new Explode();
+ newTransition = true;
+ } else if ("moveImage".equals(name)) {
+ transition = new MoveImage();
newTransition = true;
} else if ("autoTransition".equals(name)) {
transition = new AutoTransition();
@@ -189,6 +194,15 @@ public class TransitionInflater {
return transition;
}
+ private Slide createSlideTransition(AttributeSet attrs) {
+ TypedArray a = mContext.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.Slide);
+ int edge = a.getInt(com.android.internal.R.styleable.Slide_slideEdge, Slide.BOTTOM);
+ Slide slide = new Slide(edge);
+ a.recycle();
+ return slide;
+ }
+
private void getTargetIds(XmlPullParser parser,
AttributeSet attrs, Transition transition) throws XmlPullParserException, IOException {
diff --git a/core/java/android/transition/TransitionPropagation.java b/core/java/android/transition/TransitionPropagation.java
new file mode 100644
index 000000000000..9a481c2dca92
--- /dev/null
+++ b/core/java/android/transition/TransitionPropagation.java
@@ -0,0 +1,88 @@
+/*
+ * 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.transition;
+
+import android.graphics.Rect;
+import android.view.ViewGroup;
+
+/**
+ * Extend <code>TransitionPropagation</code> to customize start delays for Animators created
+ * in {@link android.transition.Transition#createAnimator(ViewGroup,
+ * TransitionValues, TransitionValues)}. A Transition such as {@link android.transition.Explode}
+ * defaults to using {@link android.transition.CircularPropagation} and Views closer to the
+ * epicenter will move out of the scene later and into the scene sooner than Views farther
+ * from the epicenter, giving the appearance of inertia. With no TransitionPropagation, all
+ * Views will react simultaneously to the start of the transition.
+ *
+ * @see Transition#setPropagation(TransitionPropagation)
+ * @see Transition#getEpicenter()
+ */
+public abstract class TransitionPropagation {
+ /**
+ * Called by Transition to alter the Animator start delay. All start delays will be adjusted
+ * such that the minimum becomes zero.
+ * @param sceneRoot The root of the View hierarchy running the transition.
+ * @param transition The transition that created the Animator
+ * @param startValues The values for a specific target in the start scene.
+ * @param endValues The values for the target in the end scene.
+ * @return A start delay to use with the Animator created by <code>transition</code>. The
+ * delay will be offset by the minimum delay of all <code>TransitionPropagation</code>s
+ * used in the Transition so that the smallest delay will be 0. Returned values may be
+ * negative.
+ */
+ public abstract long getStartDelay(ViewGroup sceneRoot, Transition transition,
+ TransitionValues startValues, TransitionValues endValues);
+
+ /**
+ * Captures the values in the start or end scene for the properties that this
+ * transition propagation monitors. These values are then passed as the startValues
+ * or endValues structure in a later call to
+ * {@link #getStartDelay(ViewGroup, Transition, TransitionValues, TransitionValues)}.
+ * The main concern for an implementation is what the
+ * properties are that the transition cares about and what the values are
+ * for all of those properties. The start and end values will be compared
+ * later during the
+ * {@link #getStartDelay(ViewGroup, Transition, TransitionValues, TransitionValues)}.
+ * method to determine the start delay.
+ *
+ * <p>Subclasses must implement this method. The method should only be called by the
+ * transition system; it is not intended to be called from external classes.</p>
+ *
+ * @param transitionValues The holder for any values that the Transition
+ * wishes to store. Values are stored in the <code>values</code> field
+ * of this TransitionValues object and are keyed from
+ * a String value. For example, to store a view's rotation value,
+ * a transition might call
+ * <code>transitionValues.values.put("appname:transitionname:rotation",
+ * view.getRotation())</code>. The target view will already be stored in
+ * the transitionValues structure when this method is called.
+ */
+ public abstract void captureValues(TransitionValues transitionValues);
+
+ /**
+ * Returns the set of property names stored in the {@link TransitionValues}
+ * object passed into {@link #captureValues(TransitionValues)} that
+ * this transition propagation cares about for the purposes of preventing
+ * duplicate capturing of property values.
+
+ * <p>A <code>TransitionPropagation</code> must override this method to prevent
+ * duplicate capturing of values and must contain at least one </p>
+ *
+ * @return An array of property names as described in the class documentation for
+ * {@link TransitionValues}.
+ */
+ public abstract String[] getPropagationProperties() ;
+}
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 19d6b3d3c393..966b24dc033a 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -17,6 +17,7 @@
package android.transition;
import android.animation.TimeInterpolator;
+import android.graphics.Rect;
import android.util.AndroidRuntimeException;
import android.view.View;
import android.view.ViewGroup;
@@ -315,6 +316,15 @@ public class TransitionSet extends Transition {
}
}
+ @Override
+ void capturePropagationValues(TransitionValues transitionValues) {
+ super.capturePropagationValues(transitionValues);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).capturePropagationValues(transitionValues);
+ }
+ }
+
/** @hide */
@Override
public void pause(View sceneRoot) {
@@ -365,6 +375,24 @@ public class TransitionSet extends Transition {
}
@Override
+ public void setPropagation(TransitionPropagation propagation) {
+ super.setPropagation(propagation);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).setPropagation(propagation);
+ }
+ }
+
+ @Override
+ public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
+ super.setEpicenterCallback(epicenterCallback);
+ int numTransitions = mTransitions.size();
+ for (int i = 0; i < numTransitions; ++i) {
+ mTransitions.get(i).setEpicenterCallback(epicenterCallback);
+ }
+ }
+
+ @Override
String toString(String indent) {
String result = super.toString(indent);
for (int i = 0; i < mTransitions.size(); ++i) {
@@ -383,5 +411,4 @@ public class TransitionSet extends Transition {
}
return clone;
}
-
}
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 44f92cd7ed4a..7783b6f0ff1c 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -17,6 +17,7 @@
package android.transition;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.view.View;
import android.view.ViewGroup;
@@ -29,15 +30,20 @@ import android.view.ViewGroup;
* information to determine the specific animations to run when visibility
* changes occur. Subclasses should implement one or both of the methods
* {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)},
- * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)},
+ * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)} or
+ * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)},
+ * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
*/
public abstract class Visibility extends Transition {
private static final String PROPNAME_VISIBILITY = "android:visibility:visibility";
private static final String PROPNAME_PARENT = "android:visibility:parent";
+ private static final String PROPNAME_SCREEN_LOCATION = "android:visibility:screenLocation";
+
private static final String[] sTransitionProperties = {
PROPNAME_VISIBILITY,
PROPNAME_PARENT,
+ PROPNAME_SCREEN_LOCATION,
};
private static class VisibilityInfo {
@@ -58,6 +64,9 @@ public abstract class Visibility extends Transition {
int visibility = transitionValues.view.getVisibility();
transitionValues.values.put(PROPNAME_VISIBILITY, visibility);
transitionValues.values.put(PROPNAME_PARENT, transitionValues.view.getParent());
+ int[] loc = new int[2];
+ transitionValues.view.getLocationOnScreen(loc);
+ transitionValues.values.put(PROPNAME_SCREEN_LOCATION, loc);
}
@Override
@@ -179,8 +188,11 @@ public abstract class Visibility extends Transition {
}
/**
- * The default implementation of this method does nothing. Subclasses
- * should override if they need to create an Animator when targets appear.
+ * The default implementation of this method calls
+ * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
+ * Subclasses should override this method or
+ * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
+ * if they need to create an Animator when targets appear.
* The method should only be called by the Visibility class; it is
* not intended to be called from external classes.
*
@@ -196,15 +208,53 @@ public abstract class Visibility extends Transition {
public Animator onAppear(ViewGroup sceneRoot,
TransitionValues startValues, int startVisibility,
TransitionValues endValues, int endVisibility) {
+ return onAppear(sceneRoot, endValues.view, startValues, endValues);
+ }
+
+ /**
+ * The default implementation of this method returns a null Animator. Subclasses should
+ * override this method to make targets appear with the desired transition. The
+ * method should only be called from
+ * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
+ *
+ * @param sceneRoot The root of the transition hierarchy
+ * @param view The View to make appear. This will be in the target scene's View hierarchy and
+ * will be VISIBLE.
+ * @param startValues The target values in the start scene
+ * @param endValues The target values in the end scene
+ * @return An Animator to be started at the appropriate time in the
+ * overall transition for this scene change. A null value means no animation
+ * should be run.
+ */
+ public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+ TransitionValues endValues) {
return null;
}
/**
- * The default implementation of this method does nothing. Subclasses
- * should override if they need to create an Animator when targets disappear.
+ * Subclasses should override this method or
+ * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}
+ * if they need to create an Animator when targets disappear.
* The method should only be called by the Visibility class; it is
* not intended to be called from external classes.
- *
+ * <p>
+ * The default implementation of this method attempts to find a View to use to call
+ * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)},
+ * based on the situation of the View in the View hierarchy. For example,
+ * if a View was simply removed from its parent, then the View will be added
+ * into a {@link android.view.ViewGroupOverlay} and passed as the <code>view</code>
+ * parameter in {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
+ * If a visible View is changed to be {@link View#GONE} or {@link View#INVISIBLE},
+ * then it can be used as the <code>view</code> and the visibility will be changed
+ * to {@link View#VISIBLE} for the duration of the animation. However, if a View
+ * is in a hierarchy which is also altering its visibility, the situation can be
+ * more complicated. In general, if a view that is no longer in the hierarchy in
+ * the end scene still has a parent (so its parent hierarchy was removed, but it
+ * was not removed from its parent), then it will be left alone to avoid side-effects from
+ * improperly removing it from its parent. The only exception to this is if
+ * the previous {@link Scene} was {@link Scene#getSceneForLayout(ViewGroup, int,
+ * android.content.Context) created from a layout resource file}, then it is considered
+ * safe to un-parent the starting scene view in order to make it disappear.</p>
*
* @param sceneRoot The root of the transition hierarchy
* @param startValues The target values in the start scene
@@ -218,6 +268,144 @@ public abstract class Visibility extends Transition {
public Animator onDisappear(ViewGroup sceneRoot,
TransitionValues startValues, int startVisibility,
TransitionValues endValues, int endVisibility) {
+ View startView = (startValues != null) ? startValues.view : null;
+ View endView = (endValues != null) ? endValues.view : null;
+ View overlayView = null;
+ View viewToKeep = null;
+ if (endView == null || endView.getParent() == null) {
+ if (endView != null) {
+ // endView was removed from its parent - add it to the overlay
+ overlayView = endView;
+ } else if (startView != null) {
+ // endView does not exist. Use startView only under certain
+ // conditions, because placing a view in an overlay necessitates
+ // it being removed from its current parent
+ if (startView.getParent() == null) {
+ // no parent - safe to use
+ overlayView = startView;
+ } else if (startView.getParent() instanceof View &&
+ startView.getParent().getParent() == null) {
+ View startParent = (View) startView.getParent();
+ int id = startParent.getId();
+ if (id != View.NO_ID && sceneRoot.findViewById(id) != null && mCanRemoveViews) {
+ // no parent, but its parent is unparented but the parent
+ // hierarchy has been replaced by a new hierarchy with the same id
+ // and it is safe to un-parent startView
+ overlayView = startView;
+ }
+ }
+ }
+ } else {
+ // visibility change
+ if (endVisibility == View.INVISIBLE) {
+ viewToKeep = endView;
+ } else {
+ // Becoming GONE
+ if (startView == endView) {
+ viewToKeep = endView;
+ } else {
+ overlayView = startView;
+ }
+ }
+ }
+ final int finalVisibility = endVisibility;
+ final ViewGroup finalSceneRoot = sceneRoot;
+
+ if (overlayView != null) {
+ // TODO: Need to do this for general case of adding to overlay
+ int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
+ int screenX = screenLoc[0];
+ int screenY = screenLoc[1];
+ int[] loc = new int[2];
+ sceneRoot.getLocationOnScreen(loc);
+ overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
+ overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
+ sceneRoot.getOverlay().add(overlayView);
+ Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
+ if (animator == null) {
+ sceneRoot.getOverlay().remove(overlayView);
+ } else {
+ final View finalOverlayView = overlayView;
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finalSceneRoot.getOverlay().remove(finalOverlayView);
+ }
+
+ @Override
+ public void onAnimationPause(Animator animation) {
+ finalSceneRoot.getOverlay().remove(finalOverlayView);
+ }
+
+ @Override
+ public void onAnimationResume(Animator animation) {
+ finalSceneRoot.getOverlay().add(finalOverlayView);
+ }
+ });
+ }
+ return animator;
+ }
+
+ if (viewToKeep != null) {
+ viewToKeep.setVisibility(View.VISIBLE);
+ Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
+ if (animator == null) {
+ viewToKeep.setVisibility(finalVisibility);
+ } else {
+ final View finalViewToKeep = viewToKeep;
+ animator.addListener(new AnimatorListenerAdapter() {
+ boolean mCanceled = false;
+
+ @Override
+ public void onAnimationPause(Animator animation) {
+ if (!mCanceled) {
+ finalViewToKeep.setVisibility(finalVisibility);
+ }
+ }
+
+ @Override
+ public void onAnimationResume(Animator animation) {
+ if (!mCanceled) {
+ finalViewToKeep.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mCanceled) {
+ finalViewToKeep.setVisibility(finalVisibility);
+ }
+ }
+ });
+ }
+ return animator;
+ }
+ return null;
+ }
+
+ /**
+ * The default implementation of this method returns a null Animator. Subclasses should
+ * override this method to make targets disappear with the desired transition. The
+ * method should only be called from
+ * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
+ *
+ * @param sceneRoot The root of the transition hierarchy
+ * @param view The View to make disappear. This will be in the target scene's View
+ * hierarchy or in an {@link android.view.ViewGroupOverlay} and will be
+ * VISIBLE.
+ * @param startValues The target values in the start scene
+ * @param endValues The target values in the end scene
+ * @return An Animator to be started at the appropriate time in the
+ * overall transition for this scene change. A null value means no animation
+ * should be run.
+ */
+ public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+ TransitionValues endValues) {
return null;
}
}
diff --git a/core/java/android/transition/VisibilityPropagation.java b/core/java/android/transition/VisibilityPropagation.java
new file mode 100644
index 000000000000..0326d4725ecd
--- /dev/null
+++ b/core/java/android/transition/VisibilityPropagation.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition;
+
+import android.view.View;
+
+/**
+ * Base class for <code>TransitionPropagation</code>s that care about
+ * View Visibility and the center position of the View.
+ */
+public abstract class VisibilityPropagation extends TransitionPropagation {
+
+ /**
+ * The property key used for {@link android.view.View#getVisibility()}.
+ */
+ private static final String PROPNAME_VISIBILITY = "android:visibilityPropagation:visibility";
+
+ /**
+ * The property key used for the center of the View in screen coordinates. This is an
+ * int[2] with the index 0 taking the x coordinate and index 1 taking the y coordinate.
+ */
+ private static final String PROPNAME_VIEW_CENTER = "android:visibilityPropagation:center";
+
+ private static final String[] VISIBILITY_PROPAGATION_VALUES = {
+ PROPNAME_VISIBILITY,
+ PROPNAME_VIEW_CENTER,
+ };
+
+ @Override
+ public void captureValues(TransitionValues values) {
+ View view = values.view;
+ values.values.put(PROPNAME_VISIBILITY, view.getVisibility());
+ int[] loc = new int[2];
+ view.getLocationOnScreen(loc);
+ loc[0] += Math.round(view.getTranslationX());
+ loc[0] += view.getWidth() / 2;
+ loc[1] += Math.round(view.getTranslationY());
+ loc[1] += view.getHeight() / 2;
+ values.values.put(PROPNAME_VIEW_CENTER, loc);
+ }
+
+ @Override
+ public String[] getPropagationProperties() {
+ return VISIBILITY_PROPAGATION_VALUES;
+ }
+
+ /**
+ * Returns {@link android.view.View#getVisibility()} for the View at the time the values
+ * were captured.
+ * @param values The TransitionValues captured at the start or end of the Transition.
+ * @return {@link android.view.View#getVisibility()} for the View at the time the values
+ * were captured.
+ */
+ public int getViewVisibility(TransitionValues values) {
+ if (values == null) {
+ return View.GONE;
+ }
+ Integer visibility = (Integer) values.values.get(PROPNAME_VISIBILITY);
+ if (visibility == null) {
+ return View.GONE;
+ }
+ return visibility;
+ }
+
+ /**
+ * Returns the View's center x coordinate, relative to the screen, at the time the values
+ * were captured.
+ * @param values The TransitionValues captured at the start or end of the Transition.
+ * @return the View's center x coordinate, relative to the screen, at the time the values
+ * were captured.
+ */
+ public int getViewX(TransitionValues values) {
+ return getViewCoordinate(values, 0);
+ }
+
+ /**
+ * Returns the View's center y coordinate, relative to the screen, at the time the values
+ * were captured.
+ * @param values The TransitionValues captured at the start or end of the Transition.
+ * @return the View's center y coordinate, relative to the screen, at the time the values
+ * were captured.
+ */
+ public int getViewY(TransitionValues values) {
+ return getViewCoordinate(values, 1);
+ }
+
+ private static int getViewCoordinate(TransitionValues values, int coordinateIndex) {
+ if (values == null) {
+ return -1;
+ }
+
+ int[] coordinates = (int[]) values.values.get(PROPNAME_VIEW_CENTER);
+ if (coordinates == null) {
+ return -1;
+ }
+
+ return coordinates[coordinateIndex];
+ }
+}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0cd6325231f6..7bd1f56cd6c2 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -18,7 +18,6 @@ package android.view;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityOptions;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -1390,11 +1389,11 @@ public abstract class Window {
* @param options Options to set or null for none
* @hide
*/
- public void setTransitionOptions(ActivityOptions options, SceneTransitionListener listener) {
+ public void setTransitionOptions(Bundle options, SceneTransitionListener listener) {
}
/**
- * A callback for Activity transitions to be told when the shared element is ready to be shown
+ * A callback for Window transitions to be told when the shared element is ready to be shown
* and start the transition to its target location.
* @hide
*/
@@ -1407,27 +1406,57 @@ public abstract class Window {
}
/**
- * Controls when the Activity enter scene is triggered and the background is faded in. If
- * triggerEarly is true, the enter scene will begin as soon as possible and the background
- * will fade in when all shared elements are ready to begin transitioning. If triggerEarly is
- * false, the Activity enter scene and background fade will be triggered when the calling
- * Activity's exit transition completes.
- *
- * @param triggerEarly Set to true to have the Activity enter scene transition in as early as
- * possible or set to false to wait for the calling Activity to exit first.
+ * Controls how the Activity's start Scene is faded in and when the enter scene
+ * is triggered to start.
+ * <p>When allow is true, the enter Scene will begin as soon as possible
+ * and the background will fade in when all shared elements are ready to begin
+ * transitioning. If allow is false, the Activity enter Scene and
+ * background fade will be triggered when the calling Activity's exit transition
+ * completes.</p>
+ * @param allow Set to true to have the Activity enter scene transition in
+ * as early as possible or set to false to wait for the calling
+ * Activity to exit first. The default value is true.
*/
- public void setTriggerEarlyEnterTransition(boolean triggerEarly) {
+ public void setAllowOverlappingEnterTransition(boolean allow) {
+ }
+
+ /**
+ * Controls how the Activity's Scene fades out and when the calling Activity's
+ * enter scene is triggered when finishing to return to a calling Activity.
+ * <p>When allow is true, the Scene will fade out quickly
+ * and inform the calling Activity to transition in when the fade completes.
+ * When allow is false, the calling Activity will transition in after
+ * the Activity's Scene has exited.
+ * </p>
+ * @param allow Set to true to have the Activity fade out as soon as possible
+ * and transition in the calling Activity. The default value is
+ * true.
+ */
+ public void setAllowOverlappingExitTransition(boolean allow) {
}
/**
* Start the exit transition.
* @hide
*/
- public Bundle startExitTransition(ActivityOptions options) {
+ public Bundle startExitTransitionToCallee(Bundle options) {
return null;
}
/**
+ * Starts the transition back to the calling Activity.
+ * onTransitionEnd will be called on the current thread if there is no exit transition.
+ * @hide
+ */
+ public void startExitTransitionToCaller(Runnable onTransitionEnd) {
+ onTransitionEnd.run();
+ }
+
+ /** @hide */
+ public void restoreViewVisibilityAfterTransitionToCallee() {
+ }
+
+ /**
* On entering Activity Scene transitions, shared element names may be mapped from a
* source Activity's specified name to a unique shared element name in the View hierarchy.
* Under most circumstances, mapping is not necessary - a single View will have the
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 1f405a7c3563..e4575e51651d 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -640,16 +640,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
@Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
- // Fill available height
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
- }
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setCanOpenPopup(true);
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 32c7086b70e8..3975edf002b4 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -20,6 +20,7 @@ import android.content.res.Configuration;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
@@ -27,6 +28,7 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.internal.view.menu.ActionMenuItemView;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.MenuView;
/**
@@ -50,6 +52,8 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
private int mMinCellSize;
private int mGeneratedItemPadding;
+ private OnMenuItemClickListener mOnMenuItemClickListener;
+
public ActionMenuView(Context context) {
this(context, null);
}
@@ -78,6 +82,10 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
}
}
+ public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
+ mOnMenuItemClickListener = listener;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// If we've been given an exact size to match, apply special formatting during layout.
@@ -96,11 +104,11 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
mMenu.onItemsChanged(true);
}
- if (mFormatItems) {
+ final int childCount = getChildCount();
+ if (mFormatItems && childCount > 0) {
onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec);
} else {
// Previous measurement at exact format may have set margins - reset them.
- final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
@@ -559,9 +567,11 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
if (mMenu == null) {
final Context context = getContext();
mMenu = new MenuBuilder(context);
+ mMenu.setCallback(new MenuBuilderCallback());
mPresenter = new ActionMenuPresenter(context);
- mPresenter.initForMenu(context, mMenu);
mPresenter.setMenuView(this);
+ mPresenter.setCallback(new ActionMenuPresenterCallback());
+ mMenu.addMenuPresenter(mPresenter);
}
return mMenu;
@@ -591,6 +601,44 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
return false;
}
+ /**
+ * Interface responsible for receiving menu item click events if the items themselves
+ * do not have individual item click listeners.
+ */
+ public interface OnMenuItemClickListener {
+ /**
+ * This method will be invoked when a menu item is clicked if the item itself did
+ * not already handle the event.
+ *
+ * @param item {@link MenuItem} that was clicked
+ * @return <code>true</code> if the event was handled, <code>false</code> otherwise.
+ */
+ public boolean onMenuItemClick(MenuItem item);
+ }
+
+ private class MenuBuilderCallback implements MenuBuilder.Callback {
+ @Override
+ public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
+ return mOnMenuItemClickListener != null &&
+ mOnMenuItemClickListener.onMenuItemClick(item);
+ }
+
+ @Override
+ public void onMenuModeChange(MenuBuilder menu) {
+ }
+ }
+
+ private class ActionMenuPresenterCallback implements ActionMenuPresenter.Callback {
+ @Override
+ public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+ }
+
+ @Override
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
+ return false;
+ }
+ }
+
/** @hide */
public interface ActionMenuChildView {
public boolean needsDividerBefore();
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
new file mode 100644
index 000000000000..075feba22ef7
--- /dev/null
+++ b/core/java/android/widget/Toolbar.java
@@ -0,0 +1,1048 @@
+/*
+ * 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.annotation.NonNull;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+import com.android.internal.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A standard toolbar for use within application content.
+ *
+ * <p>A Toolbar is a generalization of {@link android.app.ActionBar action bars} for use
+ * within application layouts. While an action bar is traditionally part of an
+ * {@link android.app.Activity Activity's} opaque window decor controlled by the framework,
+ * a Toolbar may be placed at any arbitrary level of nesting within a view hierarchy.
+ * An application may choose to designate a Toolbar as the action bar for an Activity
+ * using the {@link android.app.Activity#setActionBar(Toolbar) setActionBar()} method.</p>
+ *
+ * <p>Toolbar supports a more focused feature set than ActionBar. From start to end, a toolbar
+ * may contain a combination of the following optional elements:
+ *
+ * <ul>
+ * <li><em>A navigation button.</em> This may be an Up arrow, navigation menu toggle, close,
+ * collapse, done or another glyph of the app's choosing. This button should always be used
+ * to access other navigational destinations within the container of the Toolbar and
+ * its signified content or otherwise leave the current context signified by the Toolbar.</li>
+ * <li><em>A branded logo image.</em> This may extend to the height of the bar and can be
+ * arbitrarily wide.</li>
+ * <li><em>A title and subtitle.</em> The title should be a signpost for the Toolbar's current
+ * position in the navigation hierarchy and the content contained there. The subtitle,
+ * if present should indicate any extended information about the current content.
+ * If an app uses a logo image it should strongly consider omitting a title and subtitle.</li>
+ * <li><em>One or more custom views.</em> The application may add arbitrary child views
+ * to the Toolbar. They will appear at this position within the layout. If a child view's
+ * {@link LayoutParams} indicates a {@link Gravity} value of
+ * {@link Gravity#CENTER_HORIZONTAL CENTER_HORIZONTAL} the view will attempt to center
+ * within the available space remaining in the Toolbar after all other elements have been
+ * measured.</li>
+ * <li><em>An {@link ActionMenuView action menu}.</em> The menu of actions will pin to the
+ * end of the Toolbar offering a few
+ * <a href="http://developer.android.com/design/patterns/actionbar.html#ActionButtons">
+ * frequent, important or typical</a> actions along with an optional overflow menu for
+ * additional actions.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>In modern Android UIs developers should lean more on a visually distinct color scheme for
+ * toolbars than on their application icon. The use of application icon plus title as a standard
+ * layout is discouraged on API 21 devices and newer.</p>
+ */
+public class Toolbar extends ViewGroup {
+ private ActionMenuView mMenuView;
+ private TextView mTitleTextView;
+ private TextView mSubtitleTextView;
+ private ImageButton mNavButtonView;
+ private ImageView mLogoView;
+
+ private int mTitleTextAppearance;
+ private int mSubtitleTextAppearance;
+ private int mTitleMarginStart;
+ private int mTitleMarginEnd;
+ private int mTitleMarginTop;
+ private int mTitleMarginBottom;
+
+ private int mGravity = Gravity.START | Gravity.CENTER_VERTICAL;
+
+ private CharSequence mTitleText;
+ private CharSequence mSubtitleText;
+
+ // Clear me after use.
+ private final ArrayList<View> mTempViews = new ArrayList<View>();
+
+ private OnMenuItemClickListener mOnMenuItemClickListener;
+
+ private final ActionMenuView.OnMenuItemClickListener mMenuViewItemClickListener =
+ new ActionMenuView.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ if (mOnMenuItemClickListener != null) {
+ return mOnMenuItemClickListener.onMenuItemClick(item);
+ }
+ return false;
+ }
+ };
+
+ public Toolbar(Context context) {
+ this(context, null);
+ }
+
+ public Toolbar(Context context, AttributeSet attrs) {
+ this(context, attrs, com.android.internal.R.attr.toolbarStyle);
+ }
+
+ public Toolbar(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public Toolbar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Toolbar,
+ defStyleAttr, defStyleRes);
+
+ mTitleTextAppearance = a.getResourceId(R.styleable.Toolbar_titleTextAppearance, 0);
+ mSubtitleTextAppearance = a.getResourceId(R.styleable.Toolbar_subtitleTextAppearance, 0);
+ mGravity = a.getInteger(R.styleable.Toolbar_gravity, mGravity);
+ mTitleMarginStart = mTitleMarginEnd = Math.max(0, a.getDimensionPixelOffset(
+ R.styleable.Toolbar_titleMargins, -1));
+
+ final int marginStart = a.getDimensionPixelOffset(R.styleable.Toolbar_titleMarginStart, -1);
+ if (marginStart >= 0) {
+ mTitleMarginStart = marginStart;
+ }
+
+ final int marginEnd = a.getDimensionPixelOffset(R.styleable.Toolbar_titleMarginEnd, -1);
+ if (marginEnd >= 0) {
+ mTitleMarginEnd = marginEnd;
+ }
+
+ final int marginTop = a.getDimensionPixelOffset(R.styleable.Toolbar_titleMarginTop, -1);
+ if (marginTop >= 0) {
+ mTitleMarginTop = marginTop;
+ }
+
+ final int marginBottom = a.getDimensionPixelOffset(R.styleable.Toolbar_titleMarginBottom,
+ -1);
+ if (marginBottom >= 0) {
+ mTitleMarginBottom = marginBottom;
+ }
+
+ final CharSequence title = a.getText(R.styleable.Toolbar_title);
+ if (!TextUtils.isEmpty(title)) {
+ setTitle(title);
+ }
+
+ final CharSequence subtitle = a.getText(R.styleable.Toolbar_subtitle);
+ if (!TextUtils.isEmpty(subtitle)) {
+ setSubtitle(title);
+ }
+ a.recycle();
+ }
+
+ /**
+ * Set a logo drawable from a resource id.
+ *
+ * <p>This drawable should generally take the place of title text. The logo cannot be
+ * clicked. Apps using a logo should also supply a description using
+ * {@link #setLogoDescription(int)}.</p>
+ *
+ * @param resId ID of a drawable resource
+ */
+ public void setLogo(int resId) {
+ setLogo(getContext().getDrawable(resId));
+ }
+
+ /**
+ * Set a logo drawable.
+ *
+ * <p>This drawable should generally take the place of title text. The logo cannot be
+ * clicked. Apps using a logo should also supply a description using
+ * {@link #setLogoDescription(int)}.</p>
+ *
+ * @param drawable Drawable to use as a logo
+ */
+ public void setLogo(Drawable drawable) {
+ if (drawable != null) {
+ if (mLogoView == null) {
+ mLogoView = new ImageView(getContext());
+ }
+ if (mLogoView.getParent() == null) {
+ addSystemView(mLogoView);
+ }
+ } else if (mLogoView != null && mLogoView.getParent() != null) {
+ removeView(mLogoView);
+ }
+ if (mLogoView != null) {
+ mLogoView.setImageDrawable(drawable);
+ }
+ }
+
+ /**
+ * Return the current logo drawable.
+ *
+ * @return The current logo drawable
+ * @see #setLogo(int)
+ * @see #setLogo(android.graphics.drawable.Drawable)
+ */
+ public Drawable getLogo() {
+ return mLogoView != null ? mLogoView.getDrawable() : null;
+ }
+
+ /**
+ * Set a description of the toolbar's logo.
+ *
+ * <p>This description will be used for accessibility or other similar descriptions
+ * of the UI.</p>
+ *
+ * @param resId String resource id
+ */
+ public void setLogoDescription(int resId) {
+ setLogoDescription(getContext().getText(resId));
+ }
+
+ /**
+ * Set a description of the toolbar's logo.
+ *
+ * <p>This description will be used for accessibility or other similar descriptions
+ * of the UI.</p>
+ *
+ * @param description Description to set
+ */
+ public void setLogoDescription(CharSequence description) {
+ if (!TextUtils.isEmpty(description) && mLogoView == null) {
+ mLogoView = new ImageView(getContext());
+ }
+ if (mLogoView != null) {
+ mLogoView.setContentDescription(description);
+ }
+ }
+
+ /**
+ * Return the description of the toolbar's logo.
+ *
+ * @return A description of the logo
+ */
+ public CharSequence getLogoDescription() {
+ return mLogoView != null ? mLogoView.getContentDescription() : null;
+ }
+
+ /**
+ * Return the current title displayed in the toolbar.
+ *
+ * @return The current title
+ */
+ public CharSequence getTitle() {
+ return mTitleText;
+ }
+
+ /**
+ * Set the title of this toolbar.
+ *
+ * <p>A title should be used as the anchor for a section of content. It should
+ * describe or name the content being viewed.</p>
+ *
+ * @param resId Resource ID of a string to set as the title
+ */
+ public void setTitle(int resId) {
+ setTitle(getContext().getText(resId));
+ }
+
+ /**
+ * Set the title of this toolbar.
+ *
+ * <p>A title should be used as the anchor for a section of content. It should
+ * describe or name the content being viewed.</p>
+ *
+ * @param title Title to set
+ */
+ public void setTitle(CharSequence title) {
+ if (!TextUtils.isEmpty(title)) {
+ if (mTitleTextView == null) {
+ final Context context = getContext();
+ mTitleTextView = new TextView(context);
+ mTitleTextView.setTextAppearance(context, mTitleTextAppearance);
+ }
+ if (mTitleTextView.getParent() == null) {
+ addSystemView(mTitleTextView);
+ }
+ } else if (mTitleTextView != null && mTitleTextView.getParent() != null) {
+ removeView(mTitleTextView);
+ }
+ if (mTitleTextView != null) {
+ mTitleTextView.setText(title);
+ }
+ mTitleText = title;
+ }
+
+ /**
+ * Return the subtitle of this toolbar.
+ *
+ * @return The current subtitle
+ */
+ public CharSequence getSubtitle() {
+ return mSubtitleText;
+ }
+
+ /**
+ * Set the subtitle of this toolbar.
+ *
+ * <p>Subtitles should express extended information about the current content.</p>
+ *
+ * @param resId String resource ID
+ */
+ public void setSubtitle(int resId) {
+ setSubtitle(getContext().getText(resId));
+ }
+
+ /**
+ * Set the subtitle of this toolbar.
+ *
+ * <p>Subtitles should express extended information about the current content.</p>
+ *
+ * @param subtitle Subtitle to set
+ */
+ public void setSubtitle(CharSequence subtitle) {
+ if (!TextUtils.isEmpty(subtitle)) {
+ if (mSubtitleTextView == null) {
+ final Context context = getContext();
+ mSubtitleTextView = new TextView(context);
+ mSubtitleTextView.setTextAppearance(context, mSubtitleTextAppearance);
+ }
+ if (mSubtitleTextView.getParent() == null) {
+ addSystemView(mSubtitleTextView);
+ }
+ } else if (mSubtitleTextView != null && mSubtitleTextView.getParent() != null) {
+ removeView(mSubtitleTextView);
+ }
+ if (mSubtitleTextView != null) {
+ mSubtitleTextView.setText(subtitle);
+ }
+ mSubtitleText = subtitle;
+ }
+
+ /**
+ * Set the icon to use for the toolbar's navigation button.
+ *
+ * <p>The navigation button appears at the start of the toolbar if present. Setting an icon
+ * will make the navigation button visible.</p>
+ *
+ * <p>If you use a navigation icon you should also set a description for its action using
+ * {@link #setNavigationDescription(int)}. This is used for accessibility and tooltips.</p>
+ *
+ * @param resId Resource ID of a drawable to set
+ */
+ public void setNavigationIcon(int resId) {
+ setNavigationIcon(getContext().getDrawable(resId));
+ }
+
+ /**
+ * Set the icon to use for the toolbar's navigation button.
+ *
+ * <p>The navigation button appears at the start of the toolbar if present. Setting an icon
+ * will make the navigation button visible.</p>
+ *
+ * <p>If you use a navigation icon you should also set a description for its action using
+ * {@link #setNavigationDescription(int)}. This is used for accessibility and tooltips.</p>
+ *
+ * @param icon Drawable to set
+ */
+ public void setNavigationIcon(Drawable icon) {
+ if (icon != null) {
+ ensureNavButtonView();
+ if (mNavButtonView.getParent() == null) {
+ addSystemView(mNavButtonView);
+ }
+ } else if (mNavButtonView != null && mNavButtonView.getParent() != null) {
+ removeView(mNavButtonView);
+ }
+ if (mNavButtonView != null) {
+ mNavButtonView.setImageDrawable(icon);
+ }
+ }
+
+ /**
+ * Return the current drawable used as the navigation icon.
+ *
+ * @return The navigation icon drawable
+ */
+ public Drawable getNavigationIcon() {
+ return mNavButtonView != null ? mNavButtonView.getDrawable() : null;
+ }
+
+ /**
+ * Set a description for the navigation button.
+ *
+ * <p>This description string is used for accessibility, tooltips and other facilities
+ * to improve discoverability.</p>
+ *
+ * @param resId Resource ID of a string to set
+ */
+ public void setNavigationDescription(int resId) {
+ setNavigationDescription(getContext().getText(resId));
+ }
+
+ /**
+ * Set a description for the navigation button.
+ *
+ * <p>This description string is used for accessibility, tooltips and other facilities
+ * to improve discoverability.</p>
+ *
+ * @param description String to set as the description
+ */
+ public void setNavigationDescription(CharSequence description) {
+ if (!TextUtils.isEmpty(description)) {
+ ensureNavButtonView();
+ }
+ if (mNavButtonView != null) {
+ mNavButtonView.setContentDescription(description);
+ }
+ }
+
+ /**
+ * Set a listener to respond to navigation events.
+ *
+ * <p>This listener will be called whenever the user clicks the navigation button
+ * at the start of the toolbar. An icon must be set for the navigation button to appear.</p>
+ *
+ * @param listener Listener to set
+ * @see #setNavigationIcon(android.graphics.drawable.Drawable)
+ */
+ public void setNavigationOnClickListener(OnClickListener listener) {
+ ensureNavButtonView();
+ mNavButtonView.setOnClickListener(listener);
+ }
+
+ /**
+ * Return the Menu shown in the toolbar.
+ *
+ * <p>Applications that wish to populate the toolbar's menu can do so from here. To use
+ * an XML menu resource, use {@link #inflateMenu(int)}.</p>
+ *
+ * @return The toolbar's Menu
+ */
+ public Menu getMenu() {
+ if (mMenuView == null) {
+ mMenuView = new ActionMenuView(getContext());
+ mMenuView.setOnMenuItemClickListener(mMenuViewItemClickListener);
+ addSystemView(mMenuView);
+ }
+ return mMenuView.getMenu();
+ }
+
+ private MenuInflater getMenuInflater() {
+ return new MenuInflater(getContext());
+ }
+
+ /**
+ * Inflate a menu resource into this toolbar.
+ *
+ * <p>Inflate an XML menu resource into this toolbar. Existing items in the menu will not
+ * be modified or removed.</p>
+ *
+ * @param resId ID of a menu resource to inflate
+ */
+ public void inflateMenu(int resId) {
+ getMenuInflater().inflate(resId, getMenu());
+ }
+
+ /**
+ * Set a listener to respond to menu item click events.
+ *
+ * <p>This listener will be invoked whenever a user selects a menu item from
+ * the action buttons presented at the end of the toolbar or the associated overflow.</p>
+ *
+ * @param listener Listener to set
+ */
+ public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
+ mOnMenuItemClickListener = listener;
+ }
+
+ private void ensureNavButtonView() {
+ if (mNavButtonView == null) {
+ mNavButtonView = new ImageButton(getContext(), null, R.attr.borderlessButtonStyle);
+ }
+ }
+
+ private void addSystemView(View v) {
+ final LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT);
+ lp.mViewType = LayoutParams.SYSTEM;
+ addView(v, lp);
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ SavedState state = new SavedState(super.onSaveInstanceState());
+ return state;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ final SavedState ss = (SavedState) state;
+ super.onRestoreInstanceState(ss.getSuperState());
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int width = 0;
+ int height = 0;
+ int childState = 0;
+
+ // System views measure first.
+
+ if (shouldLayout(mNavButtonView)) {
+ measureChildWithMargins(mNavButtonView, widthMeasureSpec, width, heightMeasureSpec, 0);
+ width += mNavButtonView.getMeasuredWidth() + getHorizontalMargins(mNavButtonView);
+ height = Math.max(height, mNavButtonView.getMeasuredHeight() +
+ getVerticalMargins(mNavButtonView));
+ childState = combineMeasuredStates(childState, mNavButtonView.getMeasuredState());
+ }
+
+ if (shouldLayout(mMenuView)) {
+ measureChildWithMargins(mMenuView, widthMeasureSpec, width, heightMeasureSpec, 0);
+ width += mMenuView.getMeasuredWidth() + getHorizontalMargins(mMenuView);
+ height = Math.max(height, mMenuView.getMeasuredHeight() +
+ getVerticalMargins(mMenuView));
+ childState = combineMeasuredStates(childState, mMenuView.getMeasuredState());
+ }
+
+ if (shouldLayout(mLogoView)) {
+ measureChildWithMargins(mLogoView, widthMeasureSpec, width, heightMeasureSpec, 0);
+ width += mLogoView.getMeasuredWidth() + getHorizontalMargins(mLogoView);
+ height = Math.max(height, mLogoView.getMeasuredHeight() +
+ getVerticalMargins(mLogoView));
+ childState = combineMeasuredStates(childState, mLogoView.getMeasuredState());
+ }
+
+ int titleWidth = 0;
+ int titleHeight = 0;
+ final int titleVertMargins = mTitleMarginTop + mTitleMarginBottom;
+ final int titleHorizMargins = mTitleMarginStart + mTitleMarginEnd;
+ if (shouldLayout(mTitleTextView)) {
+ measureChildWithMargins(mTitleTextView, widthMeasureSpec, width + titleHorizMargins,
+ heightMeasureSpec, titleVertMargins);
+ titleWidth = mTitleTextView.getMeasuredWidth() + getHorizontalMargins(mTitleTextView);
+ titleHeight = mTitleTextView.getMeasuredHeight() + getVerticalMargins(mTitleTextView);
+ childState = combineMeasuredStates(childState, mTitleTextView.getMeasuredState());
+ }
+ if (shouldLayout(mSubtitleTextView)) {
+ measureChildWithMargins(mSubtitleTextView, widthMeasureSpec, width + titleHorizMargins,
+ heightMeasureSpec, titleHeight + titleVertMargins);
+ titleWidth = Math.max(titleWidth, mSubtitleTextView.getMeasuredWidth() +
+ getHorizontalMargins(mSubtitleTextView));
+ titleHeight += mSubtitleTextView.getMeasuredHeight() +
+ getVerticalMargins(mSubtitleTextView);
+ childState = combineMeasuredStates(childState, mSubtitleTextView.getMeasuredState());
+ }
+
+ width += titleWidth;
+ height = Math.max(height, titleHeight);
+
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (lp.mViewType == LayoutParams.SYSTEM || !shouldLayout(child)) {
+ // We already got all system views above. Skip them and GONE views.
+ continue;
+ }
+
+ measureChildWithMargins(child, widthMeasureSpec, width, heightMeasureSpec, 0);
+ width += child.getMeasuredWidth() + getHorizontalMargins(child);
+ height = Math.max(height, child.getMeasuredHeight() + getVerticalMargins(child));
+ childState = combineMeasuredStates(childState, child.getMeasuredState());
+ }
+
+ // Measurement already took padding into account for available space for the children,
+ // add it in for the final size.
+ width += getPaddingLeft() + getPaddingRight();
+ height += getPaddingTop() + getPaddingBottom();
+
+ final int measuredWidth = resolveSizeAndState(
+ Math.max(width, getSuggestedMinimumWidth()),
+ widthMeasureSpec, childState & MEASURED_STATE_MASK);
+ final int measuredHeight = resolveSizeAndState(
+ Math.max(height, getSuggestedMinimumHeight()),
+ heightMeasureSpec, childState << MEASURED_HEIGHT_STATE_SHIFT);
+ setMeasuredDimension(measuredWidth, measuredHeight);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ final int width = getWidth();
+ final int height = getHeight();
+ final int paddingLeft = getPaddingLeft();
+ final int paddingRight = getPaddingRight();
+ final int paddingTop = getPaddingTop();
+ final int paddingBottom = getPaddingBottom();
+ int left = paddingLeft;
+ int right = width - paddingRight;
+
+ if (shouldLayout(mNavButtonView)) {
+ if (isRtl) {
+ right = layoutChildRight(mNavButtonView, right);
+ } else {
+ left = layoutChildLeft(mNavButtonView, left);
+ }
+ }
+
+ if (shouldLayout(mMenuView)) {
+ if (isRtl) {
+ left = layoutChildLeft(mMenuView, left);
+ } else {
+ right = layoutChildRight(mMenuView, right);
+ }
+ }
+
+ if (shouldLayout(mLogoView)) {
+ if (isRtl) {
+ right = layoutChildRight(mLogoView, right);
+ } else {
+ left = layoutChildLeft(mLogoView, left);
+ }
+ }
+
+ final boolean layoutTitle = shouldLayout(mTitleTextView);
+ final boolean layoutSubtitle = shouldLayout(mSubtitleTextView);
+ int titleHeight = 0;
+ if (layoutTitle) {
+ final LayoutParams lp = (LayoutParams) mTitleTextView.getLayoutParams();
+ titleHeight += lp.topMargin + mTitleTextView.getMeasuredHeight() + lp.bottomMargin;
+ }
+ if (layoutSubtitle) {
+ final LayoutParams lp = (LayoutParams) mSubtitleTextView.getLayoutParams();
+ titleHeight += lp.bottomMargin + mTitleTextView.getMeasuredHeight() + lp.bottomMargin;
+ }
+
+ if (layoutTitle || layoutSubtitle) {
+ int titleTop;
+ switch (mGravity & Gravity.VERTICAL_GRAVITY_MASK) {
+ case Gravity.TOP:
+ titleTop = getPaddingTop();
+ break;
+ default:
+ case Gravity.CENTER_VERTICAL:
+ final View child = layoutTitle ? mTitleTextView : mSubtitleTextView;
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ final int space = height - paddingTop - paddingBottom;
+ int spaceAbove = (space - titleHeight) / 2;
+ if (spaceAbove < lp.topMargin + mTitleMarginTop) {
+ spaceAbove = lp.topMargin + mTitleMarginTop;
+ } else {
+ final int spaceBelow = height - paddingBottom - titleHeight -
+ spaceAbove - paddingTop;
+ if (spaceBelow < lp.bottomMargin + mTitleMarginBottom) {
+ spaceAbove = Math.max(0, spaceAbove -
+ (lp.bottomMargin + mTitleMarginBottom - spaceBelow));
+ }
+ }
+ titleTop = paddingTop + spaceAbove;
+ break;
+ case Gravity.BOTTOM:
+ titleTop = height - paddingBottom - titleHeight;
+ break;
+ }
+ if (isRtl) {
+ int titleRight = right;
+ int subtitleRight = right;
+ titleTop += mTitleMarginTop;
+ if (layoutTitle) {
+ final LayoutParams lp = (LayoutParams) mTitleTextView.getLayoutParams();
+ titleRight -= lp.rightMargin + mTitleMarginStart;
+ titleTop += lp.topMargin;
+ final int titleLeft = titleRight - mTitleTextView.getMeasuredWidth();
+ final int titleBottom = titleTop + mTitleTextView.getMeasuredHeight();
+ mTitleTextView.layout(titleLeft, titleTop, titleRight, titleBottom);
+ titleRight = titleLeft - lp.leftMargin - mTitleMarginEnd;
+ titleTop = titleBottom + lp.bottomMargin;
+ }
+ if (layoutSubtitle) {
+ final LayoutParams lp = (LayoutParams) mSubtitleTextView.getLayoutParams();
+ subtitleRight -= lp.rightMargin + mTitleMarginStart;
+ titleTop += lp.topMargin;
+ final int subtitleLeft = subtitleRight - mSubtitleTextView.getMeasuredWidth();
+ final int subtitleBottom = titleTop + mSubtitleTextView.getMeasuredHeight();
+ mSubtitleTextView.layout(subtitleLeft, titleTop, subtitleRight, subtitleBottom);
+ subtitleRight = subtitleRight - lp.leftMargin - mTitleMarginEnd;
+ titleTop = subtitleBottom + lp.bottomMargin;
+ }
+ right = Math.max(titleRight, subtitleRight);
+ } else {
+ int titleLeft = left;
+ int subtitleLeft = left;
+ titleTop += mTitleMarginTop;
+ if (layoutTitle) {
+ final LayoutParams lp = (LayoutParams) mTitleTextView.getLayoutParams();
+ titleLeft += lp.leftMargin + mTitleMarginStart;
+ titleTop += lp.topMargin;
+ final int titleRight = titleLeft + mTitleTextView.getMeasuredWidth();
+ final int titleBottom = titleTop + mTitleTextView.getMeasuredHeight();
+ mTitleTextView.layout(titleLeft, titleTop, titleRight, titleBottom);
+ titleLeft = titleRight + lp.rightMargin + mTitleMarginEnd;
+ titleTop = titleBottom + lp.bottomMargin;
+ }
+ if (layoutSubtitle) {
+ final LayoutParams lp = (LayoutParams) mSubtitleTextView.getLayoutParams();
+ subtitleLeft += lp.leftMargin + mTitleMarginStart;
+ titleTop += lp.topMargin;
+ final int subtitleRight = subtitleLeft + mSubtitleTextView.getMeasuredWidth();
+ final int subtitleBottom = titleTop + mSubtitleTextView.getMeasuredHeight();
+ mSubtitleTextView.layout(subtitleLeft, titleTop, subtitleRight, subtitleBottom);
+ subtitleLeft = subtitleRight + lp.rightMargin + mTitleMarginEnd;
+ titleTop = subtitleBottom + lp.bottomMargin;
+ }
+ left = Math.max(titleLeft, subtitleLeft);
+ }
+ }
+
+ // Get all remaining children sorted for layout. This is all prepared
+ // such that absolute layout direction can be used below.
+
+ addCustomViewsWithGravity(mTempViews, Gravity.LEFT);
+ final int leftViewsCount = mTempViews.size();
+ for (int i = 0; i < leftViewsCount; i++) {
+ left = layoutChildLeft(getChildAt(i), left);
+ }
+
+ addCustomViewsWithGravity(mTempViews, Gravity.RIGHT);
+ final int rightViewsCount = mTempViews.size();
+ for (int i = 0; i < rightViewsCount; i++) {
+ right = layoutChildRight(getChildAt(i), right);
+ }
+
+ // Centered views try to center with respect to the whole bar, but views pinned
+ // to the left or right can push the mass of centered views to one side or the other.
+ addCustomViewsWithGravity(mTempViews, Gravity.CENTER);
+ final int centerViewsWidth = getViewListMeasuredWidth(mTempViews);
+ final int parentCenter = paddingLeft + (width - paddingLeft - paddingRight) / 2;
+ final int halfCenterViewsWidth = centerViewsWidth / 2;
+ int centerLeft = parentCenter - halfCenterViewsWidth;
+ final int centerRight = centerLeft + centerViewsWidth;
+ if (centerLeft < left) {
+ centerLeft = left;
+ } else if (centerRight > right) {
+ centerLeft -= centerRight - right;
+ }
+
+ final int centerViewsCount = mTempViews.size();
+ for (int i = 0; i < centerViewsCount; i++) {
+ centerLeft = layoutChildLeft(getChildAt(i), centerLeft);
+ }
+ mTempViews.clear();
+ }
+
+ private int getViewListMeasuredWidth(List<View> views) {
+ int width = 0;
+ final int count = views.size();
+ for (int i = 0; i < count; i++) {
+ final View v = views.get(i);
+ final LayoutParams lp = (LayoutParams) v.getLayoutParams();
+ width += lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
+ }
+ return width;
+ }
+
+ private int layoutChildLeft(View child, int left) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ left += lp.leftMargin;
+ int top = getChildTop(child);
+ child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
+ left += lp.rightMargin;
+ return left;
+ }
+
+ private int layoutChildRight(View child, int right) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ right -= lp.rightMargin;
+ int top = getChildTop(child);
+ child.layout(right - child.getMeasuredWidth(), top, right, top + child.getMeasuredHeight());
+ right -= lp.leftMargin;
+ return right;
+ }
+
+ private int getChildTop(View child) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ switch (getChildVerticalGravity(lp.gravity)) {
+ case Gravity.TOP:
+ return getPaddingTop();
+
+ case Gravity.BOTTOM:
+ return getPaddingBottom() - child.getMeasuredHeight() - lp.bottomMargin;
+
+ default:
+ case Gravity.CENTER_VERTICAL:
+ final int paddingTop = getPaddingTop();
+ final int paddingBottom = getPaddingBottom();
+ final int height = getHeight();
+ final int childHeight = child.getMeasuredHeight();
+ final int space = height - paddingTop - paddingBottom;
+ int spaceAbove = (space - childHeight) / 2;
+ if (spaceAbove < lp.topMargin) {
+ spaceAbove = lp.topMargin;
+ } else {
+ final int spaceBelow = height - paddingBottom - childHeight -
+ spaceAbove - paddingTop;
+ if (spaceBelow < lp.bottomMargin) {
+ spaceAbove = Math.max(0, spaceAbove - (lp.bottomMargin - spaceBelow));
+ }
+ }
+ return paddingTop + spaceAbove;
+ }
+ }
+
+ private int getChildVerticalGravity(int gravity) {
+ final int vgrav = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+ switch (vgrav) {
+ case Gravity.TOP:
+ case Gravity.BOTTOM:
+ case Gravity.CENTER_VERTICAL:
+ return vgrav;
+ default:
+ return mGravity & Gravity.VERTICAL_GRAVITY_MASK;
+ }
+ }
+
+ /**
+ * Prepare a list of non-SYSTEM child views. If the layout direction is RTL
+ * this will be in reverse child order.
+ *
+ * @param views List to populate. It will be cleared before use.
+ * @param gravity Horizontal gravity to match against
+ */
+ private void addCustomViewsWithGravity(List<View> views, int gravity) {
+ final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ final int childCount = getChildCount();
+ final int absGrav = Gravity.getAbsoluteGravity(gravity, getLayoutDirection());
+
+ views.clear();
+
+ if (isRtl) {
+ for (int i = childCount - 1; i >= 0; i--) {
+ final View child = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (lp.mViewType != LayoutParams.SYSTEM && shouldLayout(child) &&
+ getChildHorizontalGravity(lp.gravity) == absGrav) {
+ views.add(child);
+ }
+
+ }
+ } else {
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (lp.mViewType != LayoutParams.SYSTEM && shouldLayout(child) &&
+ getChildHorizontalGravity(lp.gravity) == absGrav) {
+ views.add(child);
+ }
+ }
+ }
+ }
+
+ private int getChildHorizontalGravity(int gravity) {
+ final int ld = getLayoutDirection();
+ final int absGrav = Gravity.getAbsoluteGravity(gravity, ld);
+ final int hGrav = absGrav & Gravity.HORIZONTAL_GRAVITY_MASK;
+ switch (hGrav) {
+ case Gravity.LEFT:
+ case Gravity.RIGHT:
+ case Gravity.CENTER_HORIZONTAL:
+ return hGrav;
+ default:
+ return ld == LAYOUT_DIRECTION_RTL ? Gravity.RIGHT : Gravity.LEFT;
+ }
+ }
+
+ private boolean shouldLayout(View view) {
+ return view != null && view.getParent() == this && view.getVisibility() != GONE;
+ }
+
+ private int getHorizontalMargins(View v) {
+ final MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
+ return mlp.getMarginStart() + mlp.getMarginEnd();
+ }
+
+ private int getVerticalMargins(View v) {
+ final MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
+ return mlp.topMargin + mlp.bottomMargin;
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return super.generateLayoutParams(attrs);
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ if (p instanceof LayoutParams) {
+ return new LayoutParams((LayoutParams) p);
+ } else if (p instanceof MarginLayoutParams) {
+ return new LayoutParams((MarginLayoutParams) p);
+ } else {
+ return new LayoutParams(p);
+ }
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return super.checkLayoutParams(p) && p instanceof LayoutParams;
+ }
+
+ private static boolean isCustomView(View child) {
+ return ((LayoutParams) child.getLayoutParams()).mViewType == LayoutParams.CUSTOM;
+ }
+
+ /**
+ * Interface responsible for receiving menu item click events if the items themselves
+ * do not have individual item click listeners.
+ */
+ public interface OnMenuItemClickListener {
+ /**
+ * This method will be invoked when a menu item is clicked if the item itself did
+ * not already handle the event.
+ *
+ * @param item {@link MenuItem} that was clicked
+ * @return <code>true</code> if the event was handled, <code>false</code> otherwise.
+ */
+ public boolean onMenuItemClick(MenuItem item);
+ }
+
+ /**
+ * Layout information for child views of Toolbars.
+ *
+ * @attr ref android.R.styleable#Toolbar_LayoutParams_layout_gravity
+ */
+ public static class LayoutParams extends MarginLayoutParams {
+ /**
+ * Gravity for the view associated with these LayoutParams.
+ *
+ * @see android.view.Gravity
+ */
+ @ViewDebug.ExportedProperty(category = "layout", mapping = {
+ @ViewDebug.IntToString(from = -1, to = "NONE"),
+ @ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"),
+ @ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"),
+ @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"),
+ @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"),
+ @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"),
+ @ViewDebug.IntToString(from = Gravity.START, to = "START"),
+ @ViewDebug.IntToString(from = Gravity.END, to = "END"),
+ @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"),
+ @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"),
+ @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
+ @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"),
+ @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"),
+ @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL")
+ })
+ public int gravity = Gravity.NO_GRAVITY;
+
+ static final int CUSTOM = 0;
+ static final int SYSTEM = 1;
+
+ int mViewType = CUSTOM;
+
+ public LayoutParams(@NonNull Context c, AttributeSet attrs) {
+ super(c, attrs);
+
+ TypedArray a = c.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.Toolbar_LayoutParams);
+ gravity = a.getInt(
+ com.android.internal.R.styleable.Toolbar_LayoutParams_layout_gravity,
+ Gravity.NO_GRAVITY);
+ a.recycle();
+ }
+
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ this.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
+ }
+
+ public LayoutParams(int width, int height, int gravity) {
+ super(width, height);
+ this.gravity = gravity;
+ }
+
+ public LayoutParams(int gravity) {
+ this(WRAP_CONTENT, MATCH_PARENT, gravity);
+ }
+
+ public LayoutParams(LayoutParams source) {
+ super(source);
+
+ this.gravity = source.gravity;
+ }
+
+ public LayoutParams(MarginLayoutParams source) {
+ super(source);
+ }
+
+ public LayoutParams(ViewGroup.LayoutParams source) {
+ super(source);
+ }
+ }
+
+ static class SavedState extends BaseSavedState {
+ public SavedState(Parcel source) {
+ super(source);
+ }
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ }
+
+ public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
+
+ @Override
+ public SavedState createFromParcel(Parcel source) {
+ return new SavedState(source);
+ }
+
+ @Override
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
new file mode 100644
index 000000000000..34156e5ec027
--- /dev/null
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.internal.app;
+
+import android.annotation.Nullable;
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.drawable.Drawable;
+import android.view.ActionMode;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.SpinnerAdapter;
+import android.widget.Toolbar;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+public class ToolbarActionBar extends ActionBar {
+ private Toolbar mToolbar;
+ private View mCustomView;
+
+ private int mDisplayOptions;
+
+ private int mNavResId;
+ private int mIconResId;
+ private int mLogoResId;
+ private Drawable mNavDrawable;
+ private Drawable mIconDrawable;
+ private Drawable mLogoDrawable;
+ private int mTitleResId;
+ private int mSubtitleResId;
+ private CharSequence mTitle;
+ private CharSequence mSubtitle;
+
+ private boolean mLastMenuVisibility;
+ private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
+ new ArrayList<OnMenuVisibilityListener>();
+
+ public ToolbarActionBar(Toolbar toolbar) {
+ mToolbar = toolbar;
+ }
+
+ @Override
+ public void setCustomView(View view) {
+ setCustomView(view, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ }
+
+ @Override
+ public void setCustomView(View view, LayoutParams layoutParams) {
+ if (mCustomView != null) {
+ mToolbar.removeView(mCustomView);
+ }
+ mCustomView = view;
+ if (view != null) {
+ mToolbar.addView(view, generateLayoutParams(layoutParams));
+ }
+ }
+
+ private Toolbar.LayoutParams generateLayoutParams(LayoutParams lp) {
+ final Toolbar.LayoutParams result = new Toolbar.LayoutParams(lp);
+ result.gravity = lp.gravity;
+ return result;
+ }
+
+ @Override
+ public void setCustomView(int resId) {
+ final LayoutInflater inflater = LayoutInflater.from(mToolbar.getContext());
+ setCustomView(inflater.inflate(resId, mToolbar, false));
+ }
+
+ @Override
+ public void setIcon(int resId) {
+ mIconResId = resId;
+ mIconDrawable = null;
+ updateToolbarLogo();
+ }
+
+ @Override
+ public void setIcon(Drawable icon) {
+ mIconResId = 0;
+ mIconDrawable = icon;
+ updateToolbarLogo();
+ }
+
+ @Override
+ public void setLogo(int resId) {
+ mLogoResId = resId;
+ mLogoDrawable = null;
+ updateToolbarLogo();
+ }
+
+ @Override
+ public void setLogo(Drawable logo) {
+ mLogoResId = 0;
+ mLogoDrawable = logo;
+ updateToolbarLogo();
+ }
+
+ private void updateToolbarLogo() {
+ Drawable drawable = null;
+ if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
+ final int resId;
+ if ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
+ resId = mLogoResId;
+ drawable = mLogoDrawable;
+ } else {
+ resId = mIconResId;
+ drawable = mIconDrawable;
+ }
+ if (resId != 0) {
+ drawable = mToolbar.getContext().getDrawable(resId);
+ }
+ }
+ mToolbar.setLogo(drawable);
+ }
+
+ @Override
+ public void setStackedBackgroundDrawable(Drawable d) {
+ // This space for rent (do nothing)
+ }
+
+ @Override
+ public void setSplitBackgroundDrawable(Drawable d) {
+ // This space for rent (do nothing)
+ }
+
+ @Override
+ public void setHomeButtonEnabled(boolean enabled) {
+ // If the nav button on a Toolbar is present, it's enabled. No-op.
+ }
+
+ @Override
+ public Context getThemedContext() {
+ return mToolbar.getContext();
+ }
+
+ @Override
+ public boolean isTitleTruncated() {
+ return super.isTitleTruncated();
+ }
+
+ @Override
+ public void setHomeAsUpIndicator(Drawable indicator) {
+ mToolbar.setNavigationIcon(indicator);
+ }
+
+ @Override
+ public void setHomeAsUpIndicator(int resId) {
+ mToolbar.setNavigationIcon(resId);
+ }
+
+ @Override
+ public void setHomeActionContentDescription(CharSequence description) {
+ mToolbar.setNavigationDescription(description);
+ }
+
+ @Override
+ public void setDefaultDisplayHomeAsUpEnabled(boolean enabled) {
+ // Do nothing
+ }
+
+ @Override
+ public void setHomeActionContentDescription(int resId) {
+ mToolbar.setNavigationDescription(resId);
+ }
+
+ @Override
+ public void setShowHideAnimationEnabled(boolean enabled) {
+ // This space for rent; no-op.
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration config) {
+ super.onConfigurationChanged(config);
+ }
+
+ @Override
+ public ActionMode startActionMode(ActionMode.Callback callback) {
+ return mToolbar.startActionMode(callback);
+ }
+
+ @Override
+ public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public void setSelectedNavigationItem(int position) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public int getSelectedNavigationIndex() {
+ return -1;
+ }
+
+ @Override
+ public int getNavigationItemCount() {
+ return 0;
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ mTitle = title;
+ mTitleResId = 0;
+ updateToolbarTitle();
+ }
+
+ @Override
+ public void setTitle(int resId) {
+ mTitleResId = resId;
+ mTitle = null;
+ updateToolbarTitle();
+ }
+
+ @Override
+ public void setSubtitle(CharSequence subtitle) {
+ mSubtitle = subtitle;
+ mSubtitleResId = 0;
+ updateToolbarTitle();
+ }
+
+ @Override
+ public void setSubtitle(int resId) {
+ mSubtitleResId = resId;
+ mSubtitle = null;
+ updateToolbarTitle();
+ }
+
+ private void updateToolbarTitle() {
+ final Context context = mToolbar.getContext();
+ CharSequence title = null;
+ CharSequence subtitle = null;
+ if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
+ title = mTitleResId != 0 ? context.getText(mTitleResId) : mTitle;
+ subtitle = mSubtitleResId != 0 ? context.getText(mSubtitleResId) : mSubtitle;
+ }
+ mToolbar.setTitle(title);
+ mToolbar.setSubtitle(subtitle);
+ }
+
+ @Override
+ public void setDisplayOptions(@DisplayOptions int options) {
+ setDisplayOptions(options, 0xffffffff);
+ }
+
+ @Override
+ public void setDisplayOptions(@DisplayOptions int options, @DisplayOptions int mask) {
+ final int oldOptions = mDisplayOptions;
+ mDisplayOptions = (options & mask) | (mDisplayOptions & ~mask);
+ final int optionsChanged = oldOptions ^ mDisplayOptions;
+ }
+
+ @Override
+ public void setDisplayUseLogoEnabled(boolean useLogo) {
+ setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO);
+ }
+
+ @Override
+ public void setDisplayShowHomeEnabled(boolean showHome) {
+ setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME);
+ }
+
+ @Override
+ public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
+ setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP);
+ }
+
+ @Override
+ public void setDisplayShowTitleEnabled(boolean showTitle) {
+ setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE);
+ }
+
+ @Override
+ public void setDisplayShowCustomEnabled(boolean showCustom) {
+ setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM);
+ }
+
+ @Override
+ public void setBackgroundDrawable(@Nullable Drawable d) {
+ mToolbar.setBackground(d);
+ }
+
+ @Override
+ public View getCustomView() {
+ return mCustomView;
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mToolbar.getTitle();
+ }
+
+ @Override
+ public CharSequence getSubtitle() {
+ return mToolbar.getSubtitle();
+ }
+
+ @Override
+ public int getNavigationMode() {
+ return NAVIGATION_MODE_STANDARD;
+ }
+
+ @Override
+ public void setNavigationMode(@NavigationMode int mode) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public int getDisplayOptions() {
+ return mDisplayOptions;
+ }
+
+ @Override
+ public Tab newTab() {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public void addTab(Tab tab) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public void addTab(Tab tab, boolean setSelected) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public void addTab(Tab tab, int position) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public void addTab(Tab tab, int position, boolean setSelected) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public void removeTab(Tab tab) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public void removeTabAt(int position) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public void removeAllTabs() {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public void selectTab(Tab tab) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public Tab getSelectedTab() {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public Tab getTabAt(int index) {
+ throw new UnsupportedOperationException(
+ "Navigation modes are not supported in toolbar action bars");
+ }
+
+ @Override
+ public int getTabCount() {
+ return 0;
+ }
+
+ @Override
+ public int getHeight() {
+ return mToolbar.getHeight();
+ }
+
+ @Override
+ public void show() {
+ // TODO: Consider a better transition for this.
+ // Right now use no automatic transition so that the app can supply one if desired.
+ mToolbar.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void hide() {
+ // TODO: Consider a better transition for this.
+ // Right now use no automatic transition so that the app can supply one if desired.
+ mToolbar.setVisibility(View.GONE);
+ }
+
+ @Override
+ public boolean isShowing() {
+ return mToolbar.getVisibility() == View.VISIBLE;
+ }
+
+ public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
+ mMenuVisibilityListeners.add(listener);
+ }
+
+ public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
+ mMenuVisibilityListeners.remove(listener);
+ }
+
+ public void dispatchMenuVisibilityChanged(boolean isVisible) {
+ if (isVisible == mLastMenuVisibility) {
+ return;
+ }
+ mLastMenuVisibility = isVisible;
+
+ final int count = mMenuVisibilityListeners.size();
+ for (int i = 0; i < count; i++) {
+ mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
+ }
+ }
+
+ @Override
+ public void captureSharedElements(Map<String, View> sharedElements) {
+ mToolbar.findSharedElements(sharedElements);
+ }
+}
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 80e1caaf26d8..c6afae07ab5a 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -60,14 +60,14 @@ import java.util.ArrayList;
import java.util.Map;
/**
- * ActionBarImpl is the ActionBar implementation used
- * by devices of all screen sizes. If it detects a compatible decor,
- * it will split contextual modes across both the ActionBarView at
- * the top of the screen and a horizontal LinearLayout at the bottom
- * which is normally hidden.
+ * WindowDecorActionBar is the ActionBar implementation used
+ * by devices of all screen sizes as part of the window decor layout.
+ * If it detects a compatible decor, it will split contextual modes
+ * across both the ActionBarView at the top of the screen and
+ * a horizontal LinearLayout at the bottom which is normally hidden.
*/
-public class ActionBarImpl extends ActionBar {
- private static final String TAG = "ActionBarImpl";
+public class WindowDecorActionBar extends ActionBar {
+ private static final String TAG = "WindowDecorActionBar";
private Context mContext;
private Context mThemedContext;
@@ -105,9 +105,6 @@ public class ActionBarImpl extends ActionBar {
private int mContextDisplayMode;
private boolean mHasEmbeddedTabs;
- final Handler mHandler = new Handler();
- Runnable mTabSelector;
-
private int mCurWindowVisibility = View.VISIBLE;
private boolean mContentAnimations = true;
@@ -157,7 +154,7 @@ public class ActionBarImpl extends ActionBar {
}
};
- public ActionBarImpl(Activity activity) {
+ public WindowDecorActionBar(Activity activity) {
mActivity = activity;
Window window = activity.getWindow();
View decor = window.getDecorView();
@@ -168,7 +165,7 @@ public class ActionBarImpl extends ActionBar {
}
}
- public ActionBarImpl(Dialog dialog) {
+ public WindowDecorActionBar(Dialog dialog) {
mDialog = dialog;
init(dialog.getWindow().getDecorView());
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 47347128604b..dfdb9aead2fd 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -41,6 +41,7 @@ interface IStatusBarService
out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications,
out int[] switches, out List<IBinder> binders);
void onPanelRevealed();
+ void onPanelHidden();
void onNotificationClick(String pkg, String tag, int id, int userId);
void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message, int userId);
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 3cceebeab443..891baea6ea8e 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -282,11 +282,6 @@ public class ActionMenuItemView extends TextView
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
- // Fill all available height.
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
- }
final boolean textVisible = hasText();
if (textVisible && mSavedPaddingLeft >= 0) {
super.setPadding(mSavedPaddingLeft, getPaddingTop(),
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index c2d22dd43609..ed075142b355 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -43,6 +43,7 @@ public class ActionBarContainer extends FrameLayout {
private Drawable mSplitBackground;
private boolean mIsSplit;
private boolean mIsStacked;
+ private int mHeight;
public ActionBarContainer(Context context) {
this(context, null);
@@ -59,6 +60,7 @@ public class ActionBarContainer extends FrameLayout {
mBackground = a.getDrawable(com.android.internal.R.styleable.ActionBar_background);
mStackedBackground = a.getDrawable(
com.android.internal.R.styleable.ActionBar_backgroundStacked);
+ mHeight = a.getDimensionPixelSize(com.android.internal.R.styleable.ActionBar_height, -1);
if (getId() == com.android.internal.R.id.split_action_bar) {
mIsSplit = true;
@@ -251,6 +253,11 @@ public class ActionBarContainer extends FrameLayout {
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (mActionBarView == null &&
+ MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST && mHeight >= 0) {
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ Math.min(mHeight, MeasureSpec.getSize(heightMeasureSpec)), MeasureSpec.AT_MOST);
+ }
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mActionBarView == null) return;
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index adb9bf8ff015..c9dff1a2f1ab 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -21,7 +21,7 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.ViewGroup;
import android.view.WindowInsets;
-import com.android.internal.app.ActionBarImpl;
+import com.android.internal.app.WindowDecorActionBar;
import android.content.Context;
import android.content.res.TypedArray;
@@ -38,7 +38,7 @@ public class ActionBarOverlayLayout extends ViewGroup {
private static final String TAG = "ActionBarOverlayLayout";
private int mActionBarHeight;
- private ActionBarImpl mActionBar;
+ private WindowDecorActionBar mActionBar;
private int mWindowVisibility = View.VISIBLE;
// The main UI elements that we handle the layout of.
@@ -88,7 +88,7 @@ public class ActionBarOverlayLayout extends ViewGroup {
Build.VERSION_CODES.KITKAT;
}
- public void setActionBar(ActionBarImpl impl) {
+ public void setActionBar(WindowDecorActionBar impl) {
mActionBar = impl;
if (getWindowToken() != null) {
// This is being initialized after being added to a window;
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 1273c4dd6e36..60631b994984 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -430,7 +430,7 @@ public class ActionBarView extends AbsActionBarView {
mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
// Span the whole width
layoutParams.width = LayoutParams.MATCH_PARENT;
- layoutParams.height = mContentHeight;
+ layoutParams.height = LayoutParams.WRAP_CONTENT;
configPresenters(builder);
menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
if (mSplitView != null) {
diff --git a/core/java/com/android/internal/widget/AutoScrollHelper.java b/core/java/com/android/internal/widget/AutoScrollHelper.java
index 7a294aa52401..0d468ca24941 100644
--- a/core/java/com/android/internal/widget/AutoScrollHelper.java
+++ b/core/java/com/android/internal/widget/AutoScrollHelper.java
@@ -892,6 +892,10 @@ public abstract class AutoScrollHelper implements View.OnTouchListener {
public boolean canTargetScrollVertically(int direction) {
final AbsListView target = mTarget;
final int itemCount = target.getCount();
+ if (itemCount == 0) {
+ return false;
+ }
+
final int childCount = target.getChildCount();
final int firstPosition = target.getFirstVisiblePosition();
final int lastPosition = firstPosition + childCount;
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 310966cb8222..e0fa9ba432a5 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -329,7 +329,7 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
SkBitmap result;
JavaPixelAllocator allocator(env);
- if (!src->copyTo(&result, dstConfig, &allocator)) {
+ if (!src->copyTo(&result, SkBitmapConfigToColorType(dstConfig), &allocator)) {
return NULL;
}
return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index b89dceda547f..7aa241ab7764 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -151,7 +151,7 @@ static SkColorType colorTypeForScaledOutput(SkColorType colorType) {
switch (colorType) {
case kUnknown_SkColorType:
case kIndex_8_SkColorType:
- return kPMColor_SkColorType;
+ return kNative_8888_SkColorType;
default:
break;
}
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 098643b1eda3..ead2de373ab5 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -62,7 +62,7 @@ public:
bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect,
SkBitmap::Config pref, int sampleSize) {
fDecoder->setSampleSize(sampleSize);
- return fDecoder->decodeRegion(bitmap, rect, pref);
+ return fDecoder->decodeSubset(bitmap, rect, pref);
}
SkImageDecoder* getDecoder() const { return fDecoder; }
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 946b8987db63..27ed0f6a5bc6 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -65,6 +65,9 @@ public:
virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
m_dstCanvas->clipRect(rect, op, antialias);
}
+ virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
+ m_dstCanvas->clipRRect(rrect, op, antialias);
+ }
virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
m_dstCanvas->clipPath(path, op, antialias);
}
@@ -73,6 +76,12 @@ private:
SkCanvas* m_dstCanvas;
};
+// Returns true if the SkCanvas's clip is non-empty.
+static jboolean hasNonEmptyClip(const SkCanvas& canvas) {
+ bool emptyClip = canvas.isClipEmpty();
+ return emptyClip ? JNI_FALSE : JNI_TRUE;
+}
+
class SkCanvasGlue {
public:
@@ -281,8 +290,8 @@ public:
r.set(SkFloatToScalar(left), SkFloatToScalar(top),
SkFloatToScalar(right), SkFloatToScalar(bottom));
SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
- bool result = c->clipRect(r);
- return result ? JNI_TRUE : JNI_FALSE;
+ c->clipRect(r);
+ return hasNonEmptyClip(*c);
}
static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
@@ -291,8 +300,9 @@ public:
SkRect r;
r.set(SkIntToScalar(left), SkIntToScalar(top),
SkIntToScalar(right), SkIntToScalar(bottom));
- bool result = GraphicsJNI::getNativeCanvas(env, jcanvas)->clipRect(r);
- return result ? JNI_TRUE : JNI_FALSE;
+ SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ c->clipRect(r);
+ return hasNonEmptyClip(*c);
}
static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
@@ -300,8 +310,8 @@ public:
NPE_CHECK_RETURN_ZERO(env, rectf);
SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
SkRect tmp;
- bool result = c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
- return result ? JNI_TRUE : JNI_FALSE;
+ c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
+ return hasNonEmptyClip(*c);
}
static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
@@ -309,8 +319,8 @@ public:
NPE_CHECK_RETURN_ZERO(env, rect);
SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
SkRect tmp;
- bool result = c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
- return result ? JNI_TRUE : JNI_FALSE;
+ c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
+ return hasNonEmptyClip(*c);
}
@@ -321,25 +331,24 @@ public:
SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
rect.set(SkFloatToScalar(left), SkFloatToScalar(top),
SkFloatToScalar(right), SkFloatToScalar(bottom));
- bool result = canvas->clipRect(rect, static_cast<SkRegion::Op>(op));
- return result ? JNI_TRUE : JNI_FALSE;
-
+ canvas->clipRect(rect, static_cast<SkRegion::Op>(op));
+ return hasNonEmptyClip(*canvas);
}
static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
jlong pathHandle, jint op) {
SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- bool result = canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
- static_cast<SkRegion::Op>(op));
- return result ? JNI_TRUE : JNI_FALSE;
+ canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
+ static_cast<SkRegion::Op>(op));
+ return hasNonEmptyClip(*canvas);
}
static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle,
jlong deviceRgnHandle, jint op) {
SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
- bool result = canvas->clipRegion(*deviceRgn, static_cast<SkRegion::Op>(op));
- return result ? JNI_TRUE : JNI_FALSE;
+ canvas->clipRegion(*deviceRgn, static_cast<SkRegion::Op>(op));
+ return hasNonEmptyClip(*canvas);
}
static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
@@ -353,7 +362,8 @@ public:
SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
SkRect rect_;
GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
- return canvas->quickReject(rect_);
+ bool result = canvas->quickReject(rect_);
+ return result ? JNI_TRUE : JNI_FALSE;
}
static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index a59ed1912441..c66c84416111 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -51,7 +51,7 @@ public:
const float* src = autoArray.ptr();
#ifdef SK_SCALAR_IS_FLOAT
- return reinterpret_cast<jlong>(new SkColorMatrixFilter(src));
+ return reinterpret_cast<jlong>(SkColorMatrixFilter::Create(src));
#else
SkASSERT(false);
#endif
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index 2cb101515586..b64ab0d9d3ea 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -175,10 +175,14 @@ static jmethodID gOutputStream_flushMethodID;
class SkJavaOutputStream : public SkWStream {
public:
SkJavaOutputStream(JNIEnv* env, jobject stream, jbyteArray storage)
- : fEnv(env), fJavaOutputStream(stream), fJavaByteArray(storage) {
+ : fEnv(env), fJavaOutputStream(stream), fJavaByteArray(storage), fBytesWritten(0) {
fCapacity = env->GetArrayLength(storage);
}
+ virtual size_t bytesWritten() const {
+ return fBytesWritten;
+ }
+
virtual bool write(const void* buffer, size_t size) {
JNIEnv* env = fEnv;
jbyteArray storage = fJavaByteArray;
@@ -213,6 +217,7 @@ public:
buffer = (void*)((char*)buffer + requested);
size -= requested;
+ fBytesWritten += requested;
}
return true;
}
@@ -226,6 +231,7 @@ private:
jobject fJavaOutputStream; // the caller owns this object
jbyteArray fJavaByteArray; // the caller owns this object
jint fCapacity;
+ size_t fBytesWritten;
};
SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
diff --git a/core/jni/android/graphics/MaskFilter.cpp b/core/jni/android/graphics/MaskFilter.cpp
index 557336688989..7dc04464a1ba 100644
--- a/core/jni/android/graphics/MaskFilter.cpp
+++ b/core/jni/android/graphics/MaskFilter.cpp
@@ -45,7 +45,7 @@ public:
static jlong createTable(JNIEnv* env, jobject, jbyteArray jtable) {
AutoJavaByteArray autoTable(env, jtable, 256);
- SkMaskFilter* filter = new SkTableMaskFilter((const uint8_t*)autoTable.ptr());
+ SkMaskFilter* filter = SkTableMaskFilter::Create((const uint8_t*)autoTable.ptr());
return reinterpret_cast<jlong>(filter);
}
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index c400c57a7e3e..d573aa8cda3e 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -123,129 +123,129 @@ public:
SkScalar ky_ = SkFloatToScalar(ky);
obj->setSkew(kx_, ky_);
}
- static jboolean setConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong aHandle, jlong bHandle) {
+ static void setConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong aHandle, jlong bHandle) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkMatrix* a = reinterpret_cast<SkMatrix*>(aHandle);
SkMatrix* b = reinterpret_cast<SkMatrix*>(bHandle);
- return obj->setConcat(*a, *b) ? JNI_TRUE : JNI_FALSE;
+ obj->setConcat(*a, *b);
}
- static jboolean preTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+ static void preTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar dx_ = SkFloatToScalar(dx);
SkScalar dy_ = SkFloatToScalar(dy);
- return obj->preTranslate(dx_, dy_) ? JNI_TRUE : JNI_FALSE;
+ obj->preTranslate(dx_, dy_);
}
- static jboolean preScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
+ static void preScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar sx_ = SkFloatToScalar(sx);
SkScalar sy_ = SkFloatToScalar(sy);
SkScalar px_ = SkFloatToScalar(px);
SkScalar py_ = SkFloatToScalar(py);
- return obj->preScale(sx_, sy_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+ obj->preScale(sx_, sy_, px_, py_);
}
- static jboolean preScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
+ static void preScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar sx_ = SkFloatToScalar(sx);
SkScalar sy_ = SkFloatToScalar(sy);
- return obj->preScale(sx_, sy_) ? JNI_TRUE : JNI_FALSE;
+ obj->preScale(sx_, sy_);
}
- static jboolean preRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
+ static void preRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar degrees_ = SkFloatToScalar(degrees);
SkScalar px_ = SkFloatToScalar(px);
SkScalar py_ = SkFloatToScalar(py);
- return obj->preRotate(degrees_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+ obj->preRotate(degrees_, px_, py_);
}
- static jboolean preRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
+ static void preRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar degrees_ = SkFloatToScalar(degrees);
- return obj->preRotate(degrees_) ? JNI_TRUE : JNI_FALSE;
+ obj->preRotate(degrees_);
}
- static jboolean preSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
+ static void preSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar kx_ = SkFloatToScalar(kx);
SkScalar ky_ = SkFloatToScalar(ky);
SkScalar px_ = SkFloatToScalar(px);
SkScalar py_ = SkFloatToScalar(py);
- return obj->preSkew(kx_, ky_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+ obj->preSkew(kx_, ky_, px_, py_);
}
- static jboolean preSkew__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky) {
+ static void preSkew__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar kx_ = SkFloatToScalar(kx);
SkScalar ky_ = SkFloatToScalar(ky);
- return obj->preSkew(kx_, ky_) ? JNI_TRUE : JNI_FALSE;
+ obj->preSkew(kx_, ky_);
}
- static jboolean preConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong otherHandle) {
+ static void preConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong otherHandle) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
- return obj->preConcat(*other) ? JNI_TRUE : JNI_FALSE;
+ obj->preConcat(*other);
}
- static jboolean postTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+ static void postTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar dx_ = SkFloatToScalar(dx);
SkScalar dy_ = SkFloatToScalar(dy);
- return obj->postTranslate(dx_, dy_) ? JNI_TRUE : JNI_FALSE;
+ obj->postTranslate(dx_, dy_);
}
- static jboolean postScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
+ static void postScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar sx_ = SkFloatToScalar(sx);
SkScalar sy_ = SkFloatToScalar(sy);
SkScalar px_ = SkFloatToScalar(px);
SkScalar py_ = SkFloatToScalar(py);
- return obj->postScale(sx_, sy_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+ obj->postScale(sx_, sy_, px_, py_);
}
- static jboolean postScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
+ static void postScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar sx_ = SkFloatToScalar(sx);
SkScalar sy_ = SkFloatToScalar(sy);
- return obj->postScale(sx_, sy_) ? JNI_TRUE : JNI_FALSE;
+ obj->postScale(sx_, sy_);
}
- static jboolean postRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
+ static void postRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar degrees_ = SkFloatToScalar(degrees);
SkScalar px_ = SkFloatToScalar(px);
SkScalar py_ = SkFloatToScalar(py);
- return obj->postRotate(degrees_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+ obj->postRotate(degrees_, px_, py_);
}
- static jboolean postRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
+ static void postRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar degrees_ = SkFloatToScalar(degrees);
- return obj->postRotate(degrees_) ? JNI_TRUE : JNI_FALSE;
+ obj->postRotate(degrees_);
}
- static jboolean postSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
+ static void postSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
SkScalar kx_ = SkFloatToScalar(kx);
SkScalar ky_ = SkFloatToScalar(ky);
SkScalar px_ = SkFloatToScalar(px);
SkScalar py_ = SkFloatToScalar(py);
- return obj->postSkew(kx_, ky_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+ obj->postSkew(kx_, ky_, px_, py_);
}
- static jboolean postSkew__FF(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloat kx, jfloat ky) {
+ static void postSkew__FF(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloat kx, jfloat ky) {
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
SkScalar kx_ = SkFloatToScalar(kx);
SkScalar ky_ = SkFloatToScalar(ky);
- return matrix->postSkew(kx_, ky_) ? JNI_TRUE : JNI_FALSE;
+ matrix->postSkew(kx_, ky_);
}
- static jboolean postConcat(JNIEnv* env, jobject clazz, jlong matrixHandle, jlong otherHandle) {
+ static void postConcat(JNIEnv* env, jobject clazz, jlong matrixHandle, jlong otherHandle) {
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
- return matrix->postConcat(*other) ? JNI_TRUE : JNI_FALSE;
+ matrix->postConcat(*other);
}
static jboolean setRectToRect(JNIEnv* env, jobject clazz, jlong matrixHandle, jobject src, jobject dst, jint stfHandle) {
@@ -374,23 +374,23 @@ static JNINativeMethod methods[] = {
{"native_setSinCos","(JFF)V", (void*) SkMatrixGlue::setSinCos__FF},
{"native_setSkew","(JFFFF)V", (void*) SkMatrixGlue::setSkew__FFFF},
{"native_setSkew","(JFF)V", (void*) SkMatrixGlue::setSkew__FF},
- {"native_setConcat","(JJJ)Z", (void*) SkMatrixGlue::setConcat},
- {"native_preTranslate","(JFF)Z", (void*) SkMatrixGlue::preTranslate},
- {"native_preScale","(JFFFF)Z", (void*) SkMatrixGlue::preScale__FFFF},
- {"native_preScale","(JFF)Z", (void*) SkMatrixGlue::preScale__FF},
- {"native_preRotate","(JFFF)Z", (void*) SkMatrixGlue::preRotate__FFF},
- {"native_preRotate","(JF)Z", (void*) SkMatrixGlue::preRotate__F},
- {"native_preSkew","(JFFFF)Z", (void*) SkMatrixGlue::preSkew__FFFF},
- {"native_preSkew","(JFF)Z", (void*) SkMatrixGlue::preSkew__FF},
- {"native_preConcat","(JJ)Z", (void*) SkMatrixGlue::preConcat},
- {"native_postTranslate","(JFF)Z", (void*) SkMatrixGlue::postTranslate},
- {"native_postScale","(JFFFF)Z", (void*) SkMatrixGlue::postScale__FFFF},
- {"native_postScale","(JFF)Z", (void*) SkMatrixGlue::postScale__FF},
- {"native_postRotate","(JFFF)Z", (void*) SkMatrixGlue::postRotate__FFF},
- {"native_postRotate","(JF)Z", (void*) SkMatrixGlue::postRotate__F},
- {"native_postSkew","(JFFFF)Z", (void*) SkMatrixGlue::postSkew__FFFF},
- {"native_postSkew","(JFF)Z", (void*) SkMatrixGlue::postSkew__FF},
- {"native_postConcat","(JJ)Z", (void*) SkMatrixGlue::postConcat},
+ {"native_setConcat","(JJJ)V", (void*) SkMatrixGlue::setConcat},
+ {"native_preTranslate","(JFF)V", (void*) SkMatrixGlue::preTranslate},
+ {"native_preScale","(JFFFF)V", (void*) SkMatrixGlue::preScale__FFFF},
+ {"native_preScale","(JFF)V", (void*) SkMatrixGlue::preScale__FF},
+ {"native_preRotate","(JFFF)V", (void*) SkMatrixGlue::preRotate__FFF},
+ {"native_preRotate","(JF)V", (void*) SkMatrixGlue::preRotate__F},
+ {"native_preSkew","(JFFFF)V", (void*) SkMatrixGlue::preSkew__FFFF},
+ {"native_preSkew","(JFF)V", (void*) SkMatrixGlue::preSkew__FF},
+ {"native_preConcat","(JJ)V", (void*) SkMatrixGlue::preConcat},
+ {"native_postTranslate","(JFF)V", (void*) SkMatrixGlue::postTranslate},
+ {"native_postScale","(JFFFF)V", (void*) SkMatrixGlue::postScale__FFFF},
+ {"native_postScale","(JFF)V", (void*) SkMatrixGlue::postScale__FF},
+ {"native_postRotate","(JFFF)V", (void*) SkMatrixGlue::postRotate__FFF},
+ {"native_postRotate","(JF)V", (void*) SkMatrixGlue::postRotate__F},
+ {"native_postSkew","(JFFFF)V", (void*) SkMatrixGlue::postSkew__FFFF},
+ {"native_postSkew","(JFF)V", (void*) SkMatrixGlue::postSkew__FF},
+ {"native_postConcat","(JJ)V", (void*) SkMatrixGlue::postConcat},
{"native_setRectToRect","(JLandroid/graphics/RectF;Landroid/graphics/RectF;I)Z", (void*) SkMatrixGlue::setRectToRect},
{"native_setPolyToPoly","(J[FI[FII)Z", (void*) SkMatrixGlue::setPolyToPoly},
{"native_invert","(JJ)Z", (void*) SkMatrixGlue::invert},
diff --git a/core/jni/android/graphics/PathEffect.cpp b/core/jni/android/graphics/PathEffect.cpp
index 280375898a10..81b46ce2beb2 100644
--- a/core/jni/android/graphics/PathEffect.cpp
+++ b/core/jni/android/graphics/PathEffect.cpp
@@ -20,7 +20,7 @@ public:
jlong outerHandle, jlong innerHandle) {
SkPathEffect* outer = reinterpret_cast<SkPathEffect*>(outerHandle);
SkPathEffect* inner = reinterpret_cast<SkPathEffect*>(innerHandle);
- SkPathEffect* effect = new SkComposePathEffect(outer, inner);
+ SkPathEffect* effect = SkComposePathEffect::Create(outer, inner);
return reinterpret_cast<jlong>(effect);
}
@@ -28,7 +28,7 @@ public:
jlong firstHandle, jlong secondHandle) {
SkPathEffect* first = reinterpret_cast<SkPathEffect*>(firstHandle);
SkPathEffect* second = reinterpret_cast<SkPathEffect*>(secondHandle);
- SkPathEffect* effect = new SkSumPathEffect(first, second);
+ SkPathEffect* effect = SkSumPathEffect::Create(first, second);
return reinterpret_cast<jlong>(effect);
}
@@ -43,7 +43,7 @@ public:
for (int i = 0; i < count; i++) {
intervals[i] = SkFloatToScalar(values[i]);
}
- SkPathEffect* effect = new SkDashPathEffect(intervals, count, SkFloatToScalar(phase));
+ SkPathEffect* effect = SkDashPathEffect::Create(intervals, count, SkFloatToScalar(phase));
return reinterpret_cast<jlong>(effect);
}
@@ -51,19 +51,19 @@ public:
jlong shapeHandle, jfloat advance, jfloat phase, jint style) {
const SkPath* shape = reinterpret_cast<SkPath*>(shapeHandle);
SkASSERT(shape != NULL);
- SkPathEffect* effect = new SkPath1DPathEffect(*shape, SkFloatToScalar(advance),
+ SkPathEffect* effect = SkPath1DPathEffect::Create(*shape, SkFloatToScalar(advance),
SkFloatToScalar(phase), (SkPath1DPathEffect::Style)style);
return reinterpret_cast<jlong>(effect);
}
static jlong Corner_constructor(JNIEnv* env, jobject, jfloat radius){
- SkPathEffect* effect = new SkCornerPathEffect(SkFloatToScalar(radius));
+ SkPathEffect* effect = SkCornerPathEffect::Create(SkFloatToScalar(radius));
return reinterpret_cast<jlong>(effect);
}
static jlong Discrete_constructor(JNIEnv* env, jobject,
jfloat length, jfloat deviation) {
- SkPathEffect* effect = new SkDiscretePathEffect(SkFloatToScalar(length),
+ SkPathEffect* effect = SkDiscretePathEffect::Create(SkFloatToScalar(length),
SkFloatToScalar(deviation));
return reinterpret_cast<jlong>(effect);
}
diff --git a/core/jni/android/graphics/Xfermode.cpp b/core/jni/android/graphics/Xfermode.cpp
index eedceb7e8360..6bf6f8a6abe9 100644
--- a/core/jni/android/graphics/Xfermode.cpp
+++ b/core/jni/android/graphics/Xfermode.cpp
@@ -36,12 +36,12 @@ public:
jint tolerance, jint modeHandle)
{
SkAvoidXfermode::Mode mode = static_cast<SkAvoidXfermode::Mode>(modeHandle);
- return reinterpret_cast<jlong>(new SkAvoidXfermode(opColor, tolerance, mode));
+ return reinterpret_cast<jlong>(SkAvoidXfermode::Create(opColor, tolerance, mode));
}
static jlong pixelxor_create(JNIEnv* env, jobject, jint opColor)
{
- return reinterpret_cast<jlong>(new SkPixelXorXfermode(opColor));
+ return reinterpret_cast<jlong>(SkPixelXorXfermode::Create(opColor));
}
};
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index d079349cb256..cf9565770d13 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -59,13 +59,14 @@ static void android_view_RenderNode_output(JNIEnv* env,
static jlong android_view_RenderNode_create(JNIEnv* env, jobject clazz) {
RenderNode* displayList = new RenderNode();
+ displayList->incStrong(0);
return reinterpret_cast<jlong>(displayList);
}
static void android_view_RenderNode_destroyDisplayList(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
- RenderNode::destroyDisplayListDeferred(displayList);
+ displayList->decStrong(0);
}
// ----------------------------------------------------------------------------
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_qntm_alpha.9.png
deleted file mode 100644
index 406bf58c96d0..000000000000
--- a/core/res/res/drawable-hdpi/ab_bottom_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.png
deleted file mode 100644
index 409d3cdc79da..000000000000
--- a/core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.png
deleted file mode 100644
index 9d7b25fa4b76..000000000000
--- a/core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.png
deleted file mode 100644
index 1222711a6c3a..000000000000
--- a/core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.png
deleted file mode 100644
index d0fcc25c9239..000000000000
--- a/core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.png
deleted file mode 100644
index 5fa4ec416859..000000000000
--- a/core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_alarm.png b/core/res/res/drawable-hdpi/ic_audio_alarm_alpha.png
index 1b41de4f70cb..1b41de4f70cb 100644
--- a/core/res/res/drawable-hdpi/ic_audio_alarm.png
+++ b/core/res/res/drawable-hdpi/ic_audio_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-hdpi/ic_audio_alarm_mute_alpha.png
index 45ed7b603a41..45ed7b603a41 100644
--- a/core/res/res/drawable-hdpi/ic_audio_alarm_mute.png
+++ b/core/res/res/drawable-hdpi/ic_audio_alarm_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_bt.png b/core/res/res/drawable-hdpi/ic_audio_bt_alpha.png
index 597c384cb7af..597c384cb7af 100644
--- a/core/res/res/drawable-hdpi/ic_audio_bt.png
+++ b/core/res/res/drawable-hdpi/ic_audio_bt_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_bt_mute.png b/core/res/res/drawable-hdpi/ic_audio_bt_mute_alpha.png
index 298db927e52c..298db927e52c 100644
--- a/core/res/res/drawable-hdpi/ic_audio_bt_mute.png
+++ b/core/res/res/drawable-hdpi/ic_audio_bt_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_notification_am.png b/core/res/res/drawable-hdpi/ic_audio_notification_am_alpha.png
index 00e8f8aec728..00e8f8aec728 100644
--- a/core/res/res/drawable-hdpi/ic_audio_notification_am.png
+++ b/core/res/res/drawable-hdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_notification_mute_am.png b/core/res/res/drawable-hdpi/ic_audio_notification_mute_am_alpha.png
index 697cc9254935..697cc9254935 100644
--- a/core/res/res/drawable-hdpi/ic_audio_notification_mute_am.png
+++ b/core/res/res/drawable-hdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_phone_am.png b/core/res/res/drawable-hdpi/ic_audio_phone_am_alpha.png
index 8a7d67ab5082..8a7d67ab5082 100644
--- a/core/res/res/drawable-hdpi/ic_audio_phone_am.png
+++ b/core/res/res/drawable-hdpi/ic_audio_phone_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_am.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_am_alpha.png
index a89f45f5b970..a89f45f5b970 100644
--- a/core/res/res/drawable-hdpi/ic_audio_ring_notif_am.png
+++ b/core/res/res/drawable-hdpi/ic_audio_ring_notif_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am_alpha.png
index d03badea7849..d03badea7849 100644
--- a/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am.png
+++ b/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am_alpha.png
index 41991067dbcc..41991067dbcc 100644
--- a/core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am.png
+++ b/core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_vol_am.png b/core/res/res/drawable-hdpi/ic_audio_vol_am_alpha.png
index 6ea269330dd5..6ea269330dd5 100644
--- a/core/res/res/drawable-hdpi/ic_audio_vol_am.png
+++ b/core/res/res/drawable-hdpi/ic_audio_vol_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_vol_mute_am.png b/core/res/res/drawable-hdpi/ic_audio_vol_mute_am_alpha.png
index 4256385a8718..4256385a8718 100644
--- a/core/res/res/drawable-hdpi/ic_audio_vol_mute_am.png
+++ b/core/res/res/drawable-hdpi/ic_audio_vol_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_airplane_mode.png b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_alpha.png
index 90c80fdb65d9..90c80fdb65d9 100644
--- a/core/res/res/drawable-hdpi/ic_lock_airplane_mode.png
+++ b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am_alpha.png
index b05589459553..b05589459553 100644
--- a/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am.png
+++ b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png
new file mode 100644
index 000000000000..ba5bd01fc7f3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-hdpi/ic_lock_idle_alarm_alpha.png
index 3cadaff0f798..3cadaff0f798 100644
--- a/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-hdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_lock.png b/core/res/res/drawable-hdpi/ic_lock_lock_alpha.png
index 6d1029ce9384..6d1029ce9384 100644
--- a/core/res/res/drawable-hdpi/ic_lock_lock.png
+++ b/core/res/res/drawable-hdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_power_off.png b/core/res/res/drawable-hdpi/ic_lock_power_off_alpha.png
index bc2dc706a385..bc2dc706a385 100644
--- a/core/res/res/drawable-hdpi/ic_lock_power_off.png
+++ b/core/res/res/drawable-hdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_ringer_off.png b/core/res/res/drawable-hdpi/ic_lock_ringer_off_alpha.png
index e7cb234bf04e..e7cb234bf04e 100644
--- a/core/res/res/drawable-hdpi/ic_lock_ringer_off.png
+++ b/core/res/res/drawable-hdpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_ringer_on.png b/core/res/res/drawable-hdpi/ic_lock_ringer_on_alpha.png
index ce0cfab936b2..ce0cfab936b2 100644
--- a/core/res/res/drawable-hdpi/ic_lock_ringer_on.png
+++ b/core/res/res/drawable-hdpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_airplane_mode.png b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_alpha.png
index 65a101bec089..65a101bec089 100644
--- a/core/res/res/drawable-ldpi/ic_lock_airplane_mode.png
+++ b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am_alpha.png
index 11adeb83a7d0..11adeb83a7d0 100644
--- a/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am.png
+++ b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_idle_alarm.png b/core/res/res/drawable-ldpi/ic_lock_idle_alarm_alpha.png
index dc133c562f2e..dc133c562f2e 100644
--- a/core/res/res/drawable-ldpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-ldpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_lock.png b/core/res/res/drawable-ldpi/ic_lock_lock_alpha.png
index bde40f6dc5cc..bde40f6dc5cc 100644
--- a/core/res/res/drawable-ldpi/ic_lock_lock.png
+++ b/core/res/res/drawable-ldpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_power_off.png b/core/res/res/drawable-ldpi/ic_lock_power_off_alpha.png
index 074d6d09c255..074d6d09c255 100644
--- a/core/res/res/drawable-ldpi/ic_lock_power_off.png
+++ b/core/res/res/drawable-ldpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_ringer_off.png b/core/res/res/drawable-ldpi/ic_lock_ringer_off_alpha.png
index 50ff3de7041c..50ff3de7041c 100644
--- a/core/res/res/drawable-ldpi/ic_lock_ringer_off.png
+++ b/core/res/res/drawable-ldpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_ringer_on.png b/core/res/res/drawable-ldpi/ic_lock_ringer_on_alpha.png
index 723272836c6f..723272836c6f 100644
--- a/core/res/res/drawable-ldpi/ic_lock_ringer_on.png
+++ b/core/res/res/drawable-ldpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.png
deleted file mode 100644
index 219d3114b6be..000000000000
--- a/core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.png
deleted file mode 100644
index bfdc933f18c3..000000000000
--- a/core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.png
deleted file mode 100644
index bd818b5f73f7..000000000000
--- a/core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.png
deleted file mode 100644
index 41c7ce616319..000000000000
--- a/core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.png
deleted file mode 100644
index 961a73e5619b..000000000000
--- a/core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.png
deleted file mode 100644
index 2e423865ee76..000000000000
--- a/core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_alarm.png b/core/res/res/drawable-mdpi/ic_audio_alarm_alpha.png
index fab95aadf09b..fab95aadf09b 100644
--- a/core/res/res/drawable-mdpi/ic_audio_alarm.png
+++ b/core/res/res/drawable-mdpi/ic_audio_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-mdpi/ic_audio_alarm_mute_alpha.png
index 451e9321b085..451e9321b085 100644
--- a/core/res/res/drawable-mdpi/ic_audio_alarm_mute.png
+++ b/core/res/res/drawable-mdpi/ic_audio_alarm_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_bt.png b/core/res/res/drawable-mdpi/ic_audio_bt_alpha.png
index 282c643ddcf9..282c643ddcf9 100644
--- a/core/res/res/drawable-mdpi/ic_audio_bt.png
+++ b/core/res/res/drawable-mdpi/ic_audio_bt_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_bt_mute.png b/core/res/res/drawable-mdpi/ic_audio_bt_mute_alpha.png
index f734c1c630bb..f734c1c630bb 100644
--- a/core/res/res/drawable-mdpi/ic_audio_bt_mute.png
+++ b/core/res/res/drawable-mdpi/ic_audio_bt_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_notification_am.png b/core/res/res/drawable-mdpi/ic_audio_notification_am_alpha.png
index b41ccd09cb15..b41ccd09cb15 100644
--- a/core/res/res/drawable-mdpi/ic_audio_notification_am.png
+++ b/core/res/res/drawable-mdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_notification_mute_am.png b/core/res/res/drawable-mdpi/ic_audio_notification_mute_am_alpha.png
index 2567f7678f33..2567f7678f33 100644
--- a/core/res/res/drawable-mdpi/ic_audio_notification_mute_am.png
+++ b/core/res/res/drawable-mdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_phone_am.png b/core/res/res/drawable-mdpi/ic_audio_phone_am_alpha.png
index beda721fdc3c..beda721fdc3c 100644
--- a/core/res/res/drawable-mdpi/ic_audio_phone_am.png
+++ b/core/res/res/drawable-mdpi/ic_audio_phone_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_am.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_am_alpha.png
index 1ce4f52d36dc..1ce4f52d36dc 100644
--- a/core/res/res/drawable-mdpi/ic_audio_ring_notif_am.png
+++ b/core/res/res/drawable-mdpi/ic_audio_ring_notif_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am_alpha.png
index cb17415d4aa3..cb17415d4aa3 100644
--- a/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am.png
+++ b/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am_alpha.png
index 2d99b7695a24..2d99b7695a24 100644
--- a/core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am.png
+++ b/core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_vol_am.png b/core/res/res/drawable-mdpi/ic_audio_vol_am_alpha.png
index c32fdbc0d70c..c32fdbc0d70c 100644
--- a/core/res/res/drawable-mdpi/ic_audio_vol_am.png
+++ b/core/res/res/drawable-mdpi/ic_audio_vol_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_vol_mute_am.png b/core/res/res/drawable-mdpi/ic_audio_vol_mute_am_alpha.png
index 0dfc21ff7ce0..0dfc21ff7ce0 100644
--- a/core/res/res/drawable-mdpi/ic_audio_vol_mute_am.png
+++ b/core/res/res/drawable-mdpi/ic_audio_vol_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_airplane_mode.png b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_alpha.png
index 2b1dc1a8c5da..2b1dc1a8c5da 100644
--- a/core/res/res/drawable-mdpi/ic_lock_airplane_mode.png
+++ b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am_alpha.png
index 49ed3d2ddb87..49ed3d2ddb87 100644
--- a/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am.png
+++ b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png
new file mode 100644
index 000000000000..4e2612df11c2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-mdpi/ic_lock_idle_alarm_alpha.png
index b5d3e0980551..b5d3e0980551 100644
--- a/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_lock.png b/core/res/res/drawable-mdpi/ic_lock_lock_alpha.png
index 5ff3654d3172..5ff3654d3172 100644
--- a/core/res/res/drawable-mdpi/ic_lock_lock.png
+++ b/core/res/res/drawable-mdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_power_off.png b/core/res/res/drawable-mdpi/ic_lock_power_off_alpha.png
index 2c55e475bac1..2c55e475bac1 100644
--- a/core/res/res/drawable-mdpi/ic_lock_power_off.png
+++ b/core/res/res/drawable-mdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_ringer_off.png b/core/res/res/drawable-mdpi/ic_lock_ringer_off_alpha.png
index 98cfb11e4081..98cfb11e4081 100644
--- a/core/res/res/drawable-mdpi/ic_lock_ringer_off.png
+++ b/core/res/res/drawable-mdpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_ringer_on.png b/core/res/res/drawable-mdpi/ic_lock_ringer_on_alpha.png
index 691b99e3b200..691b99e3b200 100644
--- a/core/res/res/drawable-mdpi/ic_lock_ringer_on.png
+++ b/core/res/res/drawable-mdpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.png
deleted file mode 100644
index 312f76c047e4..000000000000
--- a/core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.png
deleted file mode 100644
index 49e0a49f9b89..000000000000
--- a/core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.png
deleted file mode 100644
index fb0d0b6b5419..000000000000
--- a/core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.png
deleted file mode 100644
index 6d8789022efc..000000000000
--- a/core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.png
deleted file mode 100644
index 58f3e0fac378..000000000000
--- a/core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.png
deleted file mode 100644
index c37ba9ee25e1..000000000000
--- a/core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_alarm.png b/core/res/res/drawable-xhdpi/ic_audio_alarm_alpha.png
index c1f56a1d6509..c1f56a1d6509 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_alarm.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-xhdpi/ic_audio_alarm_mute_alpha.png
index 0d7034f2f0ef..0d7034f2f0ef 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_alarm_mute.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_alarm_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_bt.png b/core/res/res/drawable-xhdpi/ic_audio_bt_alpha.png
index b8aa083ac178..b8aa083ac178 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_bt.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_bt_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_bt_mute.png b/core/res/res/drawable-xhdpi/ic_audio_bt_mute_alpha.png
index 93a248178a35..93a248178a35 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_bt_mute.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_bt_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_notification_am.png b/core/res/res/drawable-xhdpi/ic_audio_notification_am_alpha.png
index 15182b952805..15182b952805 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_notification_am.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am.png b/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am_alpha.png
index c26b839bd577..c26b839bd577 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_phone_am.png b/core/res/res/drawable-xhdpi/ic_audio_phone_am_alpha.png
index 2a04619b4faa..2a04619b4faa 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_phone_am.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_phone_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_am.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_am_alpha.png
index 0df19342106c..0df19342106c 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_am.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am_alpha.png
index 85acb93db2b5..85acb93db2b5 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
index 122c7081c0ee..122c7081c0ee 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_vol_am.png b/core/res/res/drawable-xhdpi/ic_audio_vol_am_alpha.png
index 4e2e20e2252c..4e2e20e2252c 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_vol_am.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_vol_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_vol_mute_am.png b/core/res/res/drawable-xhdpi/ic_audio_vol_mute_am_alpha.png
index 64a52150192e..64a52150192e 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_vol_mute_am.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_vol_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode.png b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_alpha.png
index dc7a9172eb76..dc7a9172eb76 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am_alpha.png
index 497ca2b81e99..497ca2b81e99 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png
new file mode 100644
index 000000000000..e6ca1ea1d623
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-xhdpi/ic_lock_idle_alarm_alpha.png
index 2822a922fa48..2822a922fa48 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_lock.png b/core/res/res/drawable-xhdpi/ic_lock_lock_alpha.png
index 086a0ca0aac4..086a0ca0aac4 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_lock.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_power_off.png b/core/res/res/drawable-xhdpi/ic_lock_power_off_alpha.png
index 530236ccd8df..530236ccd8df 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_power_off.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_ringer_off.png b/core/res/res/drawable-xhdpi/ic_lock_ringer_off_alpha.png
index dff2c8932660..dff2c8932660 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_ringer_off.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_ringer_on.png b/core/res/res/drawable-xhdpi/ic_lock_ringer_on_alpha.png
index 98341b06265f..98341b06265f 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_ringer_on.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.png
deleted file mode 100644
index 65b8d4af6194..000000000000
--- a/core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.png
deleted file mode 100644
index a397baadf22c..000000000000
--- a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.png
deleted file mode 100644
index b56fa4ad1614..000000000000
--- a/core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.png
deleted file mode 100644
index 71b9737011b0..000000000000
--- a/core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.png
deleted file mode 100644
index e2cc71531b7c..000000000000
--- a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
deleted file mode 100644
index 605d1de1e107..000000000000
--- a/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_alarm.png b/core/res/res/drawable-xxhdpi/ic_audio_alarm_alpha.png
index c1c3d35514d4..c1c3d35514d4 100755
--- a/core/res/res/drawable-xxhdpi/ic_audio_alarm.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute_alpha.png
index 4bcee685021a..4bcee685021a 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_bt.png b/core/res/res/drawable-xxhdpi/ic_audio_bt_alpha.png
index 140edac614b5..140edac614b5 100755
--- a/core/res/res/drawable-xxhdpi/ic_audio_bt.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_bt_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_bt_mute.png b/core/res/res/drawable-xxhdpi/ic_audio_bt_mute_alpha.png
index 97829b456fda..97829b456fda 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_bt_mute.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_bt_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_am.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png
index fb0e96e86813..fb0e96e86813 100755
--- a/core/res/res/drawable-xxhdpi/ic_audio_notification_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am_alpha.png
index 3aa7b53fd4cc..3aa7b53fd4cc 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_phone_am.png b/core/res/res/drawable-xxhdpi/ic_audio_phone_am_alpha.png
index 1fd54a10eaa8..1fd54a10eaa8 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_phone_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_phone_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am_alpha.png
index 699711c62c99..699711c62c99 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am_alpha.png
index 19d92ba60917..19d92ba60917 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
index fdcfd56d20d2..fdcfd56d20d2 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_vol_am.png b/core/res/res/drawable-xxhdpi/ic_audio_vol_am_alpha.png
index 15b63116b30b..15b63116b30b 100755
--- a/core/res/res/drawable-xxhdpi/ic_audio_vol_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_vol_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am.png b/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am_alpha.png
index b8f41119a13d..b8f41119a13d 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode.png b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_alpha.png
index 116b891d869e..116b891d869e 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am_alpha.png
index 5ca72edae31b..5ca72edae31b 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png
new file mode 100644
index 000000000000..d6018dd5d8f0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm_alpha.png
index ed2d3c528523..ed2d3c528523 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_lock.png b/core/res/res/drawable-xxhdpi/ic_lock_lock_alpha.png
index 1b8882c7a81f..1b8882c7a81f 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_lock.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_power_off.png b/core/res/res/drawable-xxhdpi/ic_lock_power_off_alpha.png
index 061dc786ed25..061dc786ed25 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_power_off.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable/ab_bottom_transparent_quantum.xml b/core/res/res/drawable/ab_bottom_transparent_quantum.xml
deleted file mode 100644
index 29df6b909c73..000000000000
--- a/core/res/res/drawable/ab_bottom_transparent_quantum.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ab_bottom_transparent_qntm_alpha"
- android:tint="?attr/colorBackground"
- android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ab_stacked_transparent_quantum.xml b/core/res/res/drawable/ab_stacked_transparent_quantum.xml
deleted file mode 100644
index bdae6b9bc399..000000000000
--- a/core/res/res/drawable/ab_stacked_transparent_quantum.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?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.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ab_stacked_transparent_qntm_alpha"
- android:tint="?attr/colorBackground"
- android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_audio_alarm.xml
index 495bfb6d59c7..d3e547088f88 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_audio_alarm.xml
@@ -15,5 +15,5 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ab_transparent_qntm_alpha"
+ android:src="@drawable/ic_audio_alarm_alpha"
android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_solid_quantum.xml b/core/res/res/drawable/ic_audio_alarm_mute.xml
index e56bb401ad4d..7d85872a925c 100644
--- a/core/res/res/drawable/ab_solid_quantum.xml
+++ b/core/res/res/drawable/ic_audio_alarm_mute.xml
@@ -15,6 +15,5 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ab_solid_qntm_alpha"
- android:tint="?attr/colorBackground"
- android:tintMode="multiply" />
+ android:src="@drawable/ic_audio_alarm_mute_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_bottom_solid_quantum.xml b/core/res/res/drawable/ic_audio_bt.xml
index 848737e30cc2..4f5af3d09588 100644
--- a/core/res/res/drawable/ab_bottom_solid_quantum.xml
+++ b/core/res/res/drawable/ic_audio_bt.xml
@@ -15,6 +15,5 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ab_bottom_solid_qntm_alpha"
- android:tint="?attr/colorBackground"
- android:tintMode="multiply" />
+ android:src="@drawable/ic_audio_bt_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_stacked_solid_quantum.xml b/core/res/res/drawable/ic_audio_bt_mute.xml
index df775afa29d0..d2004c0efdd3 100644
--- a/core/res/res/drawable/ab_stacked_solid_quantum.xml
+++ b/core/res/res/drawable/ic_audio_bt_mute.xml
@@ -15,6 +15,5 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ab_stacked_solid_qntm_alpha"
- android:tint="?attr/colorBackground"
- android:tintMode="multiply" />
+ android:src="@drawable/ic_audio_bt_mute_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_notification.xml b/core/res/res/drawable/ic_audio_notification.xml
index b87e4c8b9d5f..65249f51ccd8 100644
--- a/core/res/res/drawable/ic_audio_notification.xml
+++ b/core/res/res/drawable/ic_audio_notification.xml
@@ -18,6 +18,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_notification_am"
- android:autoMirrored="true">
-</bitmap>
+ android:src="@drawable/ic_audio_notification_am_alpha"
+ android:autoMirrored="true"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_notification_mute.xml b/core/res/res/drawable/ic_audio_notification_mute.xml
index 1caf27c4e318..af6a8e053fcf 100644
--- a/core/res/res/drawable/ic_audio_notification_mute.xml
+++ b/core/res/res/drawable/ic_audio_notification_mute.xml
@@ -18,6 +18,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_notification_mute_am"
- android:autoMirrored="true">
-</bitmap>
+ android:src="@drawable/ic_audio_notification_mute_am_alpha"
+ android:autoMirrored="true"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_phone.xml b/core/res/res/drawable/ic_audio_phone.xml
index e6869fd0582c..1bab863b426e 100644
--- a/core/res/res/drawable/ic_audio_phone.xml
+++ b/core/res/res/drawable/ic_audio_phone.xml
@@ -18,6 +18,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_phone_am"
- android:autoMirrored="true">
-</bitmap>
+ android:src="@drawable/ic_audio_phone_am_alpha"
+ android:autoMirrored="true"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_ring_notif.xml b/core/res/res/drawable/ic_audio_ring_notif.xml
index 2f48741ea768..247d1b48f850 100644
--- a/core/res/res/drawable/ic_audio_ring_notif.xml
+++ b/core/res/res/drawable/ic_audio_ring_notif.xml
@@ -18,6 +18,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_ring_notif_am"
- android:autoMirrored="true">
-</bitmap>
+ android:src="@drawable/ic_audio_ring_notif_am_alpha"
+ android:autoMirrored="true"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_ring_notif_mute.xml b/core/res/res/drawable/ic_audio_ring_notif_mute.xml
index 7549f6dc046a..72aaa9dc04ea 100644
--- a/core/res/res/drawable/ic_audio_ring_notif_mute.xml
+++ b/core/res/res/drawable/ic_audio_ring_notif_mute.xml
@@ -18,6 +18,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_ring_notif_mute_am"
- android:autoMirrored="true">
-</bitmap>
+ android:src="@drawable/ic_audio_ring_notif_mute_am_alpha"
+ android:autoMirrored="true"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml b/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml
index 3481e27861eb..9e31aba1305c 100644
--- a/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml
+++ b/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml
@@ -18,6 +18,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_ring_notif_vibrate_am"
- android:autoMirrored="true">
-</bitmap>
+ android:src="@drawable/ic_audio_ring_notif_vibrate_am_alpha"
+ android:autoMirrored="true"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_vol.xml b/core/res/res/drawable/ic_audio_vol.xml
index 6dd249bf0fb2..8d07ded12f2a 100644
--- a/core/res/res/drawable/ic_audio_vol.xml
+++ b/core/res/res/drawable/ic_audio_vol.xml
@@ -18,6 +18,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_vol_am"
- android:autoMirrored="true">
-</bitmap>
+ android:src="@drawable/ic_audio_vol_am_alpha"
+ android:autoMirrored="true"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_vol_mute.xml b/core/res/res/drawable/ic_audio_vol_mute.xml
index b093f59242db..edbdb23878fb 100644
--- a/core/res/res/drawable/ic_audio_vol_mute.xml
+++ b/core/res/res/drawable/ic_audio_vol_mute.xml
@@ -18,6 +18,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_vol_mute_am"
- android:autoMirrored="true">
-</bitmap>
+ android:src="@drawable/ic_audio_vol_mute_am_alpha"
+ android:autoMirrored="true"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_lock_airplane_mode.xml b/core/res/res/drawable/ic_lock_airplane_mode.xml
new file mode 100644
index 000000000000..4a169224379a
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_airplane_mode.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_lock_airplane_mode_alpha"
+ android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/ic_lock_airplane_mode_off.xml b/core/res/res/drawable/ic_lock_airplane_mode_off.xml
index b344e28ef25f..a8cd390fd0b9 100644
--- a/core/res/res/drawable/ic_lock_airplane_mode_off.xml
+++ b/core/res/res/drawable/ic_lock_airplane_mode_off.xml
@@ -18,6 +18,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_lock_airplane_mode_off_am"
- android:autoMirrored="true">
-</bitmap>
+ android:src="@drawable/ic_lock_airplane_mode_off_am_alpha"
+ android:autoMirrored="true"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_lock_bugreport.xml b/core/res/res/drawable/ic_lock_bugreport.xml
new file mode 100644
index 000000000000..a3f82ce92589
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_bugreport.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_lock_bugreport_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_lock_idle_alarm.xml b/core/res/res/drawable/ic_lock_idle_alarm.xml
new file mode 100644
index 000000000000..e8189bd111d4
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_idle_alarm.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_lock_idle_alarm_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_lock_lock.xml b/core/res/res/drawable/ic_lock_lock.xml
new file mode 100644
index 000000000000..39f268a9d6ae
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_lock.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_lock_lock_alpha"
+ android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/ic_lock_power_off.xml b/core/res/res/drawable/ic_lock_power_off.xml
new file mode 100644
index 000000000000..718f17ed0c19
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_power_off.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_lock_power_off_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/layout/alert_dialog_quantum.xml b/core/res/res/layout/alert_dialog_quantum.xml
index 59dba08eddac..98b687973ebd 100644
--- a/core/res/res/layout/alert_dialog_quantum.xml
+++ b/core/res/res/layout/alert_dialog_quantum.xml
@@ -35,9 +35,10 @@
android:paddingEnd="16dip"
android:paddingTop="16dip">
<ImageView android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingEnd="8dip"
+ android:layout_width="32dip"
+ android:layout_height="32dip"
+ android:layout_marginEnd="8dip"
+ android:scaleType="fitCenter"
android:src="@null" />
<TextView android:id="@+id/alertTitle"
style="?android:attr/windowTitleStyle"
@@ -101,10 +102,6 @@
android:maxLines="2"
android:minHeight="@dimen/alert_dialog_button_bar_height"
style="?android:attr/buttonBarButtonStyle" />
- <View android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:visibility="invisible" />
<Button android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/core/res/res/layout/dialog_custom_title_quantum.xml b/core/res/res/layout/dialog_custom_title_quantum.xml
index f8a2bf7509cd..1bb93eb61f39 100644
--- a/core/res/res/layout/dialog_custom_title_quantum.xml
+++ b/core/res/res/layout/dialog_custom_title_quantum.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- 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.
@@ -23,17 +23,12 @@ This is a custom layout for a dialog.
android:fitsSystemWindows="true">
<FrameLayout android:id="@android:id/title_container"
android:layout_width="match_parent"
- android:layout_height="@dimen/alert_dialog_title_height"
android:layout_weight="0"
android:gravity="center_vertical|start"
- style="?android:attr/windowTitleBackgroundStyle">
- </FrameLayout>
- <View android:id="@+id/titleDivider"
- android:layout_width="match_parent"
- android:layout_height="2dip"
- android:background="@android:color/holo_blue_light" />
+ style="?android:attr/windowTitleBackgroundStyle" />
<FrameLayout
- android:layout_width="match_parent" android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:foreground="?android:attr/windowContentOverlay">
diff --git a/core/res/res/layout/dialog_title_icons_quantum.xml b/core/res/res/layout/dialog_title_icons_quantum.xml
index e3d771cbf2be..28e20d93ffc3 100644
--- a/core/res/res/layout/dialog_title_icons_quantum.xml
+++ b/core/res/res/layout/dialog_title_icons_quantum.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- 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.
@@ -28,9 +28,9 @@ enabled.
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
- android:minHeight="@android:dimen/alert_dialog_title_height"
android:paddingStart="16dip"
- android:paddingEnd="16dip">
+ android:paddingEnd="16dip"
+ android:paddingTop="16dip">
<ImageView android:id="@+id/left_icon"
android:layout_width="32dip"
android:layout_height="32dip"
@@ -48,11 +48,6 @@ enabled.
android:layout_marginStart="8dip" />
</LinearLayout>
- <View android:id="@+id/titleDivider"
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="@android:color/holo_blue_light" />
-
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_quantum.xml b/core/res/res/layout/dialog_title_quantum.xml
index 0a692ee61c94..b92c1e701726 100644
--- a/core/res/res/layout/dialog_title_quantum.xml
+++ b/core/res/res/layout/dialog_title_quantum.xml
@@ -1,21 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- 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.
+-->
+
+<!--
This is an optimized layout for a screen, with the minimum set of features
enabled.
-->
@@ -23,17 +22,16 @@ enabled.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
- <TextView android:id="@android:id/title" style="?android:attr/windowTitleStyle"
+ <TextView android:id="@+id/alertTitle"
+ style="?android:attr/windowTitleStyle"
+ android:singleLine="true"
+ android:ellipsize="end"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="@android:dimen/alert_dialog_title_height"
+ android:textAlignment="viewStart"
android:paddingStart="16dip"
android:paddingEnd="16dip"
- android:gravity="center_vertical|start" />
- <View android:id="@+id/titleDivider"
- android:layout_width="match_parent"
- android:layout_height="2dip"
- android:background="@android:color/holo_blue_light" />
+ android:paddingTop="16dip" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index b1afec13075b..77f537b32837 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -24,7 +24,7 @@ This is an optimized layout for a screen with the Action Bar enabled.
android:layout_width="match_parent"
android:layout_height="match_parent"
android:splitMotionEvents="false"
- android:theme="?attr/actionBarWidgetTheme">
+ android:theme="?attr/actionBarTheme">
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
@@ -33,25 +33,25 @@ This is an optimized layout for a screen with the Action Bar enabled.
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
- style="?android:attr/actionBarStyle"
+ style="?attr/actionBarStyle"
android:sharedElementName="android:action_bar"
android:gravity="top">
<com.android.internal.widget.ActionBarView
android:id="@+id/action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="?android:attr/actionBarStyle" />
+ style="?attr/actionBarStyle" />
<com.android.internal.widget.ActionBarContextView
android:id="@+id/action_context_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
- style="?android:attr/actionModeStyle" />
+ style="?attr/actionModeStyle" />
</com.android.internal.widget.ActionBarContainer>
<com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="?android:attr/actionBarSplitStyle"
+ style="?attr/actionBarSplitStyle"
android:visibility="gone"
android:gravity="center"/>
</com.android.internal.widget.ActionBarOverlayLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index aa5005f00eac..46cb9b22728a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -650,6 +650,8 @@
<!-- Default ActivityChooserView style. -->
<attr name="activityChooserViewStyle" format="reference" />
+ <attr name="toolbarStyle" format="reference" />
+
<!-- Fast scroller styles -->
<eat-comment />
@@ -689,6 +691,10 @@
buttons. actionBarStyle is still used for the primary
bar. -->
<attr name="actionBarSplitStyle" format="reference" />
+ <!-- Reference to a theme that should be used to inflate the
+ action bar. This will be inherited by any widget inflated
+ into the action bar. -->
+ <attr name="actionBarTheme" format="reference" />
<!-- Reference to a theme that should be used to inflate widgets
and layouts destined for the action bar. Most of the time
this will be a reference to the current theme, but when
@@ -911,8 +917,14 @@
<!-- ============= -->
<!-- Color palette -->
<!-- ============= -->
+ <attr name="colorPrimaryDark" format="color" />
+ <attr name="colorPrimary" format="color" />
+ <attr name="colorPrimaryLight" format="color" />
+ <attr name="colorAccent" format="color" />
+
<attr name="colorControlNormal" format="color" />
<attr name="colorControlActivated" format="color" />
+
<attr name="colorButtonNormal" format="color" />
<attr name="colorButtonPressed" format="color" />
<attr name="colorButtonNormalColored" format="color" />
@@ -4889,6 +4901,24 @@
</attr>
</declare-styleable>
+ <!-- Use <code>slide</code>as the root tag of the XML resource that
+ describes a {@link android.transition.Slide Slide} transition.
+ The attributes of the {@link android.R.styleable#Transition Transition}
+ resource are available in addition to the specific attributes of Slide
+ described here. -->
+ <declare-styleable name="Slide">
+ <attr name="slideEdge">
+ <!-- Slide to and from the bottom edge of the Scene. -->
+ <enum name="left" value="0" />
+ <!-- Slide to and from the bottom edge of the Scene. -->
+ <enum name="top" value="1" />
+ <!-- Slide to and from the bottom edge of the Scene. -->
+ <enum name="right" value="2" />
+ <!-- Slide to and from the bottom edge of the Scene. -->
+ <enum name="bottom" value="3" />
+ </attr>
+ </declare-styleable>
+
<!-- Use <code>target</code> as the root tag of the XML resource that
describes a {@link android.transition.Transition#addTarget(int)
targetId} of a transition. There can be one or more targets inside
@@ -6235,10 +6265,6 @@
<attr name="inputType" />
</declare-styleable>
- <declare-styleable name="ActionBar_LayoutParams">
- <attr name="layout_gravity" />
- </declare-styleable>
-
<declare-styleable name="Switch">
<!-- Drawable to use as the "thumb" that switches back and forth. -->
<attr name="thumb" />
@@ -6447,4 +6473,25 @@
<attr name="textView" format="reference" />
</declare-styleable>
+ <declare-styleable name="Toolbar">
+ <attr name="titleTextAppearance" format="reference" />
+ <attr name="subtitleTextAppearance" format="reference" />
+ <attr name="title" />
+ <attr name="subtitle" />
+ <attr name="gravity" />
+ <attr name="titleMargins" format="dimension" />
+ <attr name="titleMarginStart" format="dimension" />
+ <attr name="titleMarginEnd" format="dimension" />
+ <attr name="titleMarginTop" format="dimension" />
+ <attr name="titleMarginBottom" format="dimension" />
+ </declare-styleable>
+
+ <declare-styleable name="Toolbar_LayoutParams">
+ <attr name="layout_gravity" />
+ </declare-styleable>
+
+ <declare-styleable name="ActionBar_LayoutParams">
+ <attr name="layout_gravity" />
+ </declare-styleable>
+
</resources>
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index d10f7c06aae2..ebe4a495cca1 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -16,16 +16,14 @@
<resources>
<color name="background_quantum_dark">@color/black</color>
- <color name="background_quantum_light">@color/quantum_grey_50</color>
- <color name="secondary_background_quantum_dark">@color/quantum_grey_700</color>
- <color name="secondary_background_quantum_light">@color/quantum_grey_100</color>
+ <color name="background_quantum_light">@color/white</color>
<color name="bright_foreground_quantum_dark">@color/background_quantum_light</color>
<color name="bright_foreground_quantum_light">@color/background_quantum_dark</color>
<!-- TODO: This is 50% alpha black -->
<color name="bright_foreground_disabled_quantum_dark">#80000000</color>
- <!-- TODO: This is 50% alpha grey_50 -->
- <color name="bright_foreground_disabled_quantum_light">#80fafafa</color>
+ <!-- TODO: This is 50% alpha white -->
+ <color name="bright_foreground_disabled_quantum_light">#80ffffff</color>
<color name="bright_foreground_inverse_quantum_dark">@color/bright_foreground_quantum_light</color>
<color name="bright_foreground_inverse_quantum_light">@color/bright_foreground_quantum_dark</color>
@@ -34,41 +32,13 @@
<color name="dim_foreground_disabled_quantum_dark">#80bebebe</color>
<color name="dim_foreground_disabled_quantum_light">#80323232</color>
- <!-- TODO: These should be theme attributes. -->
- <color name="control_normal_foreground_quantum_light">@color/secondary_text_quantum_light</color>
- <color name="control_activated_foreground_quantum_light">@color/quantum_teal_700</color>
-
- <!-- TODO: These should be theme attributes. -->
- <color name="control_normal_foreground_quantum_dark">@color/secondary_text_quantum_dark</color>
- <color name="control_activated_foreground_quantum_dark">@color/quantum_lime_A200</color>
-
- <!-- TODO: These should be theme attributes. -->
- <color name="btn_default_normal_quantum_light">@color/quantum_grey_300</color>
- <color name="btn_default_pressed_quantum_light">@color/quantum_grey_500</color>
-
- <!-- TODO: These should be theme attributes. -->
- <color name="btn_default_normal_quantum_dark">@color/quantum_grey_700</color>
- <color name="btn_default_pressed_quantum_dark">@color/quantum_grey_500</color>
-
<color name="hint_foreground_quantum_dark">@color/bright_foreground_disabled_quantum_dark</color>
<color name="hint_foreground_quantum_light">@color/bright_foreground_disabled_quantum_light</color>
- <!-- TODO: This is 40% alpha lime_A200 -->
- <color name="highlighted_text_quantum_dark">#66eeff41</color>
- <!-- TODO: This is 40% alpha teal_700 -->
+ <!-- TODO: This is 40% alpha teal_A200 -->
+ <color name="highlighted_text_quantum_dark">#660097a7</color>
+ <!-- TODO: This is 40% alpha teal_A200 -->
<color name="highlighted_text_quantum_light">#660097a7</color>
- <!-- TODO: These should all be pushed into a TimePicker widget style. -->
- <color name="timepicker_default_background_quantum_dark">@color/background_quantum_dark</color>
- <color name="timepicker_default_background_quantum_light">@color/background_quantum_light</color>
- <color name="timepicker_default_text_color_quantum_dark">@color/bright_foreground_quantum_dark</color>
- <color name="timepicker_default_text_color_quantum_light">@color/bright_foreground_quantum_light</color>
- <color name="timepicker_default_disabled_color_quantum_dark">@color/bright_foreground_disabled_quantum_dark</color>
- <color name="timepicker_default_disabled_color_quantum_light">@color/bright_foreground_disabled_quantum_light</color>
- <color name="timepicker_default_ampm_selected_background_color_quantum_dark">@color/control_activated_foreground_quantum_dark</color>
- <color name="timepicker_default_ampm_selected_background_color_quantum_light">@color/control_activated_foreground_quantum_light</color>
- <color name="timepicker_default_ampm_unselected_background_color_quantum_dark">@color/transparent</color>
- <color name="timepicker_default_ampm_unselected_background_color_quantum_light">@color/white</color>
-
<!-- Primary & accent colors -->
<color name="quantum_red_100">#fff4c7c3</color>
@@ -155,10 +125,4 @@
<color name="primary_text_quantum_dark">#deffffff</color>
<color name="secondary_text_quantum_dark">#8affffff</color>
<color name="tertiary_text_quantum_dark">#4dffffff</color>
-
- <!-- "Theme" colors to be replaced by attrs when available -->
- <color name="theme_color_100">@color/quantum_teal_100</color>
- <color name="theme_color_300">@color/quantum_teal_300</color>
- <color name="theme_color_500">@color/quantum_teal_500</color>
- <color name="theme_color_700">@color/quantum_teal_700</color>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7ae5a037d16a..fbe066a42213 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -467,6 +467,7 @@
1 UI_MODE_TYPE_NORMAL
4 UI_MODE_TYPE_TELEVISION
5 UI_MODE_TYPE_APPLIANCE
+ 6 UI_MODE_TYPE_WATCH
Any other values will have surprising consequences. -->
<integer name="config_defaultUiModeType">1</integer>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 667addeaeee2..0233b736f63c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2143,6 +2143,10 @@
<public type="attr" name="colorButtonNormalColored" />
<public type="attr" name="colorButtonPressedColored" />
<public type="attr" name="persistable" />
+ <public type="attr" name="titleTextAppearance" />
+ <public type="attr" name="subtitleTextAppearance" />
+ <public type="attr" name="slideEdge" />
+ <public type="attr" name="actionBarTheme" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index be875ffb2b04..fc0fccc91bb9 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1208,6 +1208,13 @@ please see styles_device_defaults.xml.
<item name="android:subtitleTextStyle">@android:style/TextAppearance.Widget.ActionMode.Subtitle</item>
</style>
+ <style name="Widget.Toolbar">
+ <item name="android:titleTextAppearance">@android:style/TextAppearance.Widget.Toolbar.Title</item>
+ <item name="android:subtitleTextAppearance">@android:style/TextAppearance.Widget.Toolbar.Subtitle</item>
+ <item name="android:minHeight">?android:attr/actionBarSize</item>
+ <item name="android:titleMargins">4dp</item>
+ </style>
+
<style name="TextAppearance.Widget.ActionBar.Title"
parent="@android:style/TextAppearance.Medium">
</style>
@@ -1225,6 +1232,14 @@ please see styles_device_defaults.xml.
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
+ <style name="TextAppearance.Widget.Toolbar.Title"
+ parent="@android:style/TextAppearance.Widget.ActionBar.Title">
+ </style>
+
+ <style name="TextAppearance.Widget.Toolbar.Subtitle"
+ parent="@android:style/TextAppearance.Widget.ActionBar.Subtitle">
+ </style>
+
<style name="Widget.ActionButton">
<item name="android:background">?android:attr/actionBarItemBackground</item>
<item name="android:paddingStart">12dip</item>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 85d8761c2d5c..dd148c441363 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -340,13 +340,13 @@ please see styles_device_defaults.xml.
<style name="TextAppearance.Quantum.TimePicker.TimeLabel" parent="TextAppearance.Quantum">
<item name="textSize">@dimen/timepicker_time_label_size</item>
- <item name="textColor">@color/timepicker_default_text_color_quantum_dark</item>
+ <item name="textColor">?attr/textColorSecondary</item>
</style>
<style name="TextAppearance.Quantum.TimePicker.AmPmLabel" parent="TextAppearance.Quantum">
<item name="textSize">@dimen/timepicker_ampm_label_size</item>
<item name="textAllCaps">true</item>
- <item name="textColor">@color/timepicker_default_text_color_quantum_dark</item>
+ <item name="textColor">?attr/textColorSecondary</item>
<item name="textStyle">bold</item>
</style>
@@ -377,11 +377,11 @@ please see styles_device_defaults.xml.
<style name="TextAppearance.Quantum.Light.CalendarViewWeekDayView" parent="TextAppearance.Quantum.CalendarViewWeekDayView"/>
<style name="TextAppearance.Quantum.Light.TimePicker.TimeLabel" parent="TextAppearance.Quantum.TimePicker.TimeLabel">
- <item name="textColor">@color/timepicker_default_text_color_quantum_light</item>
+ <item name="textColor">?attr/textColorSecondary</item>
</style>
<style name="TextAppearance.Quantum.Light.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.TimePicker.AmPmLabel">
- <item name="textColor">@color/timepicker_default_text_color_quantum_light</item>
+ <item name="textColor">?attr/textColorSecondary</item>
</style>
<!-- Widget Styles -->
@@ -545,16 +545,16 @@ please see styles_device_defaults.xml.
<style name="Widget.Quantum.TimePicker" parent="Widget.TimePicker">
<item name="legacyLayout">@layout/time_picker_legacy_holo</item>
<item name="internalLayout">@layout/time_picker_holo</item>
- <item name="disabledColor">@color/timepicker_default_disabled_color_quantum_dark</item>
- <item name="headerSelectedTextColor">@color/holo_blue_light</item>
- <item name="headerUnselectedTextColor">@color/timepicker_default_text_color_quantum_dark</item>
- <item name="headerBackgroundColor">@color/timepicker_default_background_quantum_dark</item>
- <item name="numbersTextColor">@color/timepicker_default_text_color_quantum_dark</item>
- <item name="numbersBackgroundColor">@color/timepicker_default_background_quantum_dark</item>
- <item name="amPmTextColor">@color/timepicker_default_text_color_quantum_dark</item>
- <item name="amPmUnselectedBackgroundColor">@color/timepicker_default_background_quantum_dark</item>
- <item name="amPmSelectedBackgroundColor">@color/holo_blue_light</item>
- <item name="numbersSelectorColor">@color/holo_blue_light</item>
+ <item name="disabledColor">@color/bright_foreground_disabled_quantum_dark</item>
+ <item name="headerSelectedTextColor">?attr/colorControlActivated</item>
+ <item name="headerUnselectedTextColor">?attr/textColorPrimary</item>
+ <item name="headerBackgroundColor">?attr/colorBackground</item>
+ <item name="numbersTextColor">?attr/textColorSecondary</item>
+ <item name="numbersBackgroundColor">?attr/colorControlNormal</item>
+ <item name="amPmTextColor">?attr/textColorSecondary</item>
+ <item name="amPmUnselectedBackgroundColor">?attr/colorControlNormal</item>
+ <item name="amPmSelectedBackgroundColor">?attr/colorControlActivated</item>
+ <item name="numbersSelectorColor">?attr/colorControlActivated</item>
</style>
<style name="Widget.Quantum.DatePicker" parent="Widget.DatePicker">
@@ -758,9 +758,9 @@ please see styles_device_defaults.xml.
<style name="Widget.Quantum.ActionBar" parent="Widget.ActionBar">
<item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
- <item name="background">@drawable/ab_transparent_quantum</item>
- <item name="backgroundStacked">@drawable/ab_stacked_transparent_quantum</item>
- <item name="backgroundSplit">@drawable/ab_bottom_transparent_quantum</item>
+ <item name="background">@null</item>
+ <item name="backgroundStacked">@null</item>
+ <item name="backgroundSplit">@null</item>
<item name="divider">?attr/dividerVertical</item>
<item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
<item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
@@ -769,16 +769,9 @@ please see styles_device_defaults.xml.
</style>
<style name="Widget.Quantum.ActionBar.Solid">
- <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
- <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
- <item name="background">@drawable/ab_solid_quantum</item>
- <item name="backgroundStacked">@drawable/ab_stacked_solid_quantum</item>
- <item name="backgroundSplit">@drawable/ab_bottom_solid_quantum</item>
- <item name="divider">?attr/dividerVertical</item>
- <item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
- <item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
- <item name="progressBarPadding">32dip</item>
- <item name="itemPadding">8dip</item>
+ <item name="background">?attr/colorPrimary</item>
+ <item name="backgroundStacked">?attr/colorPrimary</item>
+ <item name="backgroundSplit">?attr/colorPrimary</item>
</style>
<style name="Widget.Quantum.ActionMode" parent="Widget.ActionMode">
@@ -869,19 +862,10 @@ please see styles_device_defaults.xml.
<style name="Widget.Quantum.Light.NumberPicker" parent="Widget.Quantum.NumberPicker"/>
- <style name="Widget.Quantum.Light.TimePicker" parent="Widget.TimePicker">
+ <style name="Widget.Quantum.Light.TimePicker" parent="Widget.Quantum.TimePicker">
<item name="legacyLayout">@layout/time_picker_legacy_holo</item>
<item name="internalLayout">@layout/time_picker_holo</item>
- <item name="disabledColor">@color/timepicker_default_disabled_color_quantum_light</item>
- <item name="headerSelectedTextColor">@color/holo_blue_light</item>
- <item name="headerUnselectedTextColor">@color/timepicker_default_text_color_quantum_light</item>
- <item name="headerBackgroundColor">@color/timepicker_default_background_quantum_light</item>
- <item name="numbersTextColor">@color/timepicker_default_text_color_quantum_light</item>
- <item name="numbersBackgroundColor">@color/timepicker_default_background_quantum_light</item>
- <item name="amPmTextColor">@color/timepicker_default_text_color_quantum_light</item>
- <item name="amPmUnselectedBackgroundColor">@color/timepicker_default_background_quantum_light</item>
- <item name="amPmSelectedBackgroundColor">@color/holo_blue_light</item>
- <item name="numbersSelectorColor">@color/holo_blue_light</item>
+ <item name="disabledColor">@color/bright_foreground_disabled_quantum_light</item>
</style>
<style name="Widget.Quantum.Light.DatePicker" parent="Widget.Quantum.DatePicker"/>
@@ -985,25 +969,18 @@ please see styles_device_defaults.xml.
<style name="Widget.Quantum.Light.ActionBar" parent="Widget.Quantum.ActionBar">
<item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
- <item name="background">@drawable/ab_transparent_quantum</item>
- <item name="backgroundStacked">@drawable/ab_stacked_transparent_quantum</item>
- <item name="backgroundSplit">@drawable/ab_bottom_transparent_quantum</item>
+ <item name="background">@null</item>
+ <item name="backgroundStacked">@null</item>
+ <item name="backgroundSplit">@null</item>
<item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum</item>
<item name="progressBarStyle">@style/Widget.Quantum.Light.ProgressBar.Horizontal</item>
<item name="indeterminateProgressStyle">@style/Widget.Quantum.Light.ProgressBar</item>
</style>
<style name="Widget.Quantum.Light.ActionBar.Solid">
- <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
- <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
- <item name="background">@drawable/ab_solid_quantum</item>
- <item name="backgroundStacked">@drawable/ab_stacked_solid_quantum</item>
- <item name="backgroundSplit">@drawable/ab_bottom_solid_quantum</item>
- <item name="divider">?attr/dividerVertical</item>
- <item name="progressBarStyle">@style/Widget.Quantum.Light.ProgressBar.Horizontal</item>
- <item name="indeterminateProgressStyle">@style/Widget.Quantum.Light.ProgressBar</item>
- <item name="progressBarPadding">32dip</item>
- <item name="itemPadding">8dip</item>
+ <item name="background">?attr/colorPrimary</item>
+ <item name="backgroundStacked">?attr/colorPrimary</item>
+ <item name="backgroundSplit">?attr/colorPrimary</item>
</style>
<style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 557dce244293..682293d7e434 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1829,4 +1829,10 @@
<java-symbol type="color" name="timepicker_default_ampm_selected_background_color_holo_light" />
<java-symbol type="array" name="config_clockTickVibePattern" />
+ <!-- From various Quantum changes -->
+ <java-symbol type="attr" name="toolbarStyle" />
+ <java-symbol type="attr" name="titleTextAppearance" />
+ <java-symbol type="attr" name="subtitleTextAppearance" />
+ <java-symbol type="drawable" name="ic_lock_bugreport" />
+
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 3c4e848f6a05..7aea81445eee 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -352,6 +352,8 @@ please see themes_device_defaults.xml.
<item name="actionBarDivider">?android:attr/dividerVertical</item>
<item name="actionBarItemBackground">?android:attr/selectableItemBackground</item>
+ <item name="toolbarStyle">@android:style/Widget.Toolbar</item>
+
<item name="dividerVertical">@drawable/divider_vertical_dark</item>
<item name="dividerHorizontal">@drawable/divider_vertical_dark</item>
<item name="buttonBarStyle">@android:style/ButtonBar</item>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index 50f1ca68c8f1..17bab3071ec1 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -288,8 +288,8 @@ please see themes_device_defaults.xml.
<item name="actionDropDownStyle">@style/Widget.Quantum.Spinner.DropDown.ActionBar</item>
<item name="actionButtonStyle">@style/Widget.Quantum.ActionButton</item>
<item name="actionOverflowButtonStyle">@style/Widget.Quantum.ActionButton.Overflow</item>
- <item name="actionModeBackground">@color/theme_color_700</item>
- <item name="actionModeSplitBackground">@color/theme_color_700</item>
+ <item name="actionModeBackground">?attr/colorPrimaryDark</item>
+ <item name="actionModeSplitBackground">?attr/colorPrimaryDark</item>
<item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum</item>
<item name="actionBarTabStyle">@style/Widget.Quantum.ActionBar.TabView</item>
<item name="actionBarTabBarStyle">@style/Widget.Quantum.ActionBar.TabBar</item>
@@ -334,7 +334,7 @@ please see themes_device_defaults.xml.
<item name="timePickerStyle">@style/Widget.Quantum.TimePicker</item>
<!-- TimePicker background color -->
- <item name="timePickerHeaderBackgroundColor">@color/timepicker_default_background_quantum_dark</item>
+ <item name="timePickerHeaderBackgroundColor">?colorBackground</item>
<!-- TimePicker Header time label text appearance -->
<item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Quantum.TimePicker.TimeLabel</item>
@@ -356,13 +356,18 @@ please see themes_device_defaults.xml.
<item name="fastScrollOverlayPosition">atThumb</item>
<!-- Color palette -->
- <item name="colorControlNormal">@color/control_normal_foreground_quantum_dark</item>
- <item name="colorControlActivated">@color/control_activated_foreground_quantum_dark</item>
- <item name="colorButtonNormal">@color/btn_default_normal_quantum_dark</item>
- <item name="colorButtonPressed">@color/btn_default_pressed_quantum_dark</item>
+ <item name="colorPrimaryDark">@color/quantum_grey_700</item>
+ <item name="colorPrimary">@color/quantum_grey_500</item>
+ <item name="colorPrimaryLight">@color/quantum_grey_100</item>
+ <item name="colorAccent">@color/quantum_teal_A200</item>
+
+ <item name="colorControlNormal">?attr/textColorSecondary</item>
+ <item name="colorControlActivated">?attr/colorPrimaryDark</item>
+ <item name="colorButtonNormal">@color/quantum_grey_700</item>
+ <item name="colorButtonPressed">@color/quantum_grey_500</item>
<!-- TODO: Remove these attrs and move into button style. -->
- <item name="colorButtonNormalColored">@color/theme_color_500</item>
- <item name="colorButtonPressedColored">@color/theme_color_300</item>
+ <item name="colorButtonNormalColored">?attr/colorPrimary</item>
+ <item name="colorButtonPressedColored">?attr/colorPrimaryDark</item>
</style>
<!-- Quantum Paper theme (light version). -->
@@ -660,7 +665,7 @@ please see themes_device_defaults.xml.
<item name="timePickerStyle">@style/Widget.Quantum.Light.TimePicker</item>
<!-- TimePicker Header background color -->
- <item name="timePickerHeaderBackgroundColor">@color/timepicker_default_background_quantum_light</item>
+ <item name="timePickerHeaderBackgroundColor">?attr/colorBackground</item>
<!-- TimePicker Header time label text appearance -->
<item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Quantum.Light.TimePicker.TimeLabel</item>
@@ -681,20 +686,25 @@ please see themes_device_defaults.xml.
<item name="fastScrollOverlayPosition">atThumb</item>
<!-- Color palette -->
- <item name="colorControlNormal">@color/control_normal_foreground_quantum_light</item>
- <item name="colorControlActivated">@color/control_activated_foreground_quantum_light</item>
- <item name="colorButtonNormal">@color/btn_default_normal_quantum_light</item>
- <item name="colorButtonPressed">@color/btn_default_pressed_quantum_light</item>
+ <item name="colorPrimaryDark">@color/quantum_grey_700</item>
+ <item name="colorPrimary">@color/quantum_grey_500</item>
+ <item name="colorPrimaryLight">@color/quantum_grey_100</item>
+ <item name="colorAccent">@color/quantum_teal_A200</item>
+
+ <item name="colorControlNormal">?attr/textColorSecondary</item>
+ <item name="colorControlActivated">?attr/colorPrimaryLight</item>
+ <item name="colorButtonNormal">@color/quantum_grey_100</item>
+ <item name="colorButtonPressed">@color/quantum_grey_500</item>
<!-- TODO: Remove these attrs and move into button style. -->
- <item name="colorButtonNormalColored">@color/theme_color_500</item>
- <item name="colorButtonPressedColored">@color/theme_color_700</item>
+ <item name="colorButtonNormalColored">?attr/colorPrimary</item>
+ <item name="colorButtonPressedColored">?attr/colorPrimaryLight</item>
</style>
<!-- Variant of the quantum (light) theme that has a solid (opaque) action bar
with an inverse color profile. The dark action bar sharply stands out against
the light content. -->
<style name="Theme.Quantum.Light.DarkActionBar">
- <item name="actionBarWidgetTheme">@style/Theme.Quantum</item>
+ <item name="actionBarTheme">@style/Theme.Quantum</item>
</style>
<!-- Variant of the quantum (dark) theme with no action bar. -->
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java
index fc2897f2418f..f4bab43e4c52 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java
@@ -466,15 +466,16 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
* bytes downloaded so far.
*
* @param id DownloadManager download id that needs to be checked.
+ * @param bytesToReceive how many bytes do we need to wait to receive.
* @throws Exception if timed out while waiting for the file to grow in size.
*/
- protected void waitToReceiveData(long id) throws Exception {
+ protected void waitToReceiveData(long id, long bytesToReceive) throws Exception {
int currentWaitTime = 0;
- long originalSize = getBytesDownloaded(id);
+ long expectedSize = getBytesDownloaded(id) + bytesToReceive;
long currentSize = 0;
- while ((currentSize = getBytesDownloaded(id)) <= originalSize) {
- Log.i(LOG_TAG, String.format("orig: %d, cur: %d. Waiting for file to be written to...",
- originalSize, currentSize));
+ while ((currentSize = getBytesDownloaded(id)) <= expectedSize) {
+ Log.i(LOG_TAG, String.format("expect: %d, cur: %d. Waiting for file to be written to...",
+ expectedSize, currentSize));
currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be written to.");
}
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
index ef48a18b0bf8..bcf2e45d5bb2 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
@@ -40,6 +40,9 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
protected static final String DOWNLOAD_FILENAME = "External93mb.apk";
protected static final long DOWNLOAD_FILESIZE = 95251708;
+ // Wait until download manager actually start downloading something
+ // Will wait for 1 MB to be downloaded.
+ private static final long EXPECTED_PROGRESS = 1024 * 1024;
private static final String FILE_CONCURRENT_DOWNLOAD_FILE_PREFIX = "file";
private static final String FILE_CONCURRENT_DOWNLOAD_FILE_EXTENSION = ".bin";
@@ -284,7 +287,7 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
dlRequest = mDownloadManager.enqueue(request);
waitForDownloadToStart(dlRequest);
// make sure we're starting to download some data...
- waitToReceiveData(dlRequest);
+ waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
// download disable
setWiFiStateOn(false);
@@ -292,27 +295,29 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
// download disable
Log.i(LOG_TAG, "Turning on airplane mode...");
setAirplaneModeOn(true);
- Thread.sleep(30 * 1000); // wait 30 secs
+ Thread.sleep(5 * 1000); // wait 5 secs
// download disable
setWiFiStateOn(true);
- Thread.sleep(30 * 1000); // wait 30 secs
+ Thread.sleep(5 * 1000); // wait 5 secs
+ waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
// download enable
Log.i(LOG_TAG, "Turning off airplane mode...");
setAirplaneModeOn(false);
Thread.sleep(5 * 1000); // wait 5 seconds
+ waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
// download disable
Log.i(LOG_TAG, "Turning off WiFi...");
setWiFiStateOn(false);
- Thread.sleep(30 * 1000); // wait 30 secs
+ Thread.sleep(5 * 1000); // wait 5 secs
// finally, turn WiFi back on and finish up the download
Log.i(LOG_TAG, "Turning on WiFi...");
setWiFiStateOn(true);
- Log.i(LOG_TAG, "Waiting up to 3 minutes for download to complete...");
- assertTrue(waitForDownload(dlRequest, 3 * 60 * 1000));
+ Log.i(LOG_TAG, "Waiting up to 10 minutes for download to complete...");
+ assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000));
ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
verifyFileSize(pfd, filesize);
} finally {
@@ -358,7 +363,7 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
dlRequest = mDownloadManager.enqueue(request);
waitForDownloadToStart(dlRequest);
// are we making any progress?
- waitToReceiveData(dlRequest);
+ waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
// download disable
Log.i(LOG_TAG, "Turning off WiFi...");
@@ -368,7 +373,7 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
// enable download...
Log.i(LOG_TAG, "Turning on WiFi again...");
setWiFiStateOn(true);
- waitToReceiveData(dlRequest);
+ waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
// download disable
Log.i(LOG_TAG, "Turning off WiFi...");
@@ -379,8 +384,8 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
Log.i(LOG_TAG, "Turning on WiFi again...");
setWiFiStateOn(true);
- Log.i(LOG_TAG, "Waiting up to 3 minutes for download to complete...");
- assertTrue(waitForDownload(dlRequest, 3 * 60 * 1000));
+ Log.i(LOG_TAG, "Waiting up to 10 minutes for download to complete...");
+ assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000));
ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
verifyFileSize(pfd, filesize);
} finally {
@@ -428,7 +433,7 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
dlRequest = mDownloadManager.enqueue(request);
waitForDownloadToStart(dlRequest);
// are we making any progress?
- waitToReceiveData(dlRequest);
+ waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
// download disable
Log.i(LOG_TAG, "Turning on Airplane mode...");
@@ -439,7 +444,7 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
Log.i(LOG_TAG, "Turning off Airplane mode...");
setAirplaneModeOn(false);
// make sure we're starting to download some data...
- waitToReceiveData(dlRequest);
+ waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
// reenable the connection to start up the download again
Log.i(LOG_TAG, "Turning on Airplane mode again...");
@@ -450,8 +455,8 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
Log.i(LOG_TAG, "Turning off Airplane mode again...");
setAirplaneModeOn(false);
- Log.i(LOG_TAG, "Waiting up to 3 minutes for donwload to complete...");
- assertTrue(waitForDownload(dlRequest, 180 * 1000)); // wait up to 3 mins before timeout
+ Log.i(LOG_TAG, "Waiting up to 10 minutes for donwload to complete...");
+ assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000)); // wait up to 10 mins
ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
verifyFileSize(pfd, filesize);
} finally {
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index aec7fa70f7b0..bf16630a13db 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -562,6 +562,7 @@ which indicates the current device orientation.</p>
<code>desk</code><br/>
<code>television<br/>
<code>appliance</code>
+ <code>watch</code>
</td>
<td>
<ul class="nolist">
@@ -573,8 +574,9 @@ which indicates the current device orientation.</p>
non-pointer interaction</li>
<li>{@code appliance}: Device is serving as an appliance, with
no display</li>
+ <li>{@code watch}: Device has a display and is worn on the wrist</li>
</ul>
- <p><em>Added in API level 8, television added in API 13.</em></p>
+ <p><em>Added in API level 8, television added in API 13, watch added in API 20.</em></p>
<p>For information about how your app can respond when the device is inserted into or
removed from a dock, read <a
href="{@docRoot}training/monitoring-device-state/docking-monitoring.html">Determining
diff --git a/docs/html/training/basics/actionbar/styling.jd b/docs/html/training/basics/actionbar/styling.jd
index 1f76e03f31e1..4128a97952d6 100644
--- a/docs/html/training/basics/actionbar/styling.jd
+++ b/docs/html/training/basics/actionbar/styling.jd
@@ -144,13 +144,13 @@ background like this:</p>
&lt;resources>
&lt;!-- the theme applied to the application or activity -->
&lt;style name="CustomActionBarTheme"
- parent="&#64;style/Theme.Holo.Light.DarkActionBar">
+ parent="&#64;android:style/Theme.Holo.Light.DarkActionBar">
&lt;item name="android:actionBarStyle">&#64;style/MyActionBar&lt;/item>
&lt;/style>
&lt;!-- ActionBar styles -->
&lt;style name="MyActionBar"
- parent="&#64;style/Widget.Holo.Light.ActionBar.Solid.Inverse">
+ parent="&#64;android:style/Widget.Holo.Light.ActionBar.Solid.Inverse">
&lt;item name="android:background">&#64;drawable/actionbar_background&lt;/item>
&lt;/style>
&lt;/resources>
diff --git a/docs/html/training/game-controllers/controller-input.jd b/docs/html/training/game-controllers/controller-input.jd
index 2c50ae1a67fb..c9517ba1dbd7 100644
--- a/docs/html/training/game-controllers/controller-input.jd
+++ b/docs/html/training/game-controllers/controller-input.jd
@@ -236,26 +236,33 @@ buttons.</p>
</tr>
<tr>
<td>Start game in main menu, or pause/unpause during game</td>
- <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_START BUTTON_START}</td>
+ <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_START BUTTON_START}<sup>*</sup></td>
</tr>
<tr>
<td>Display menu</td>
- <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_SELECT BUTTON_SELECT} and
-{@link android.view.KeyEvent#KEYCODE_MENU}</td>
+ <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_SELECT BUTTON_SELECT}<sup>*</sup>
+ and {@link android.view.KeyEvent#KEYCODE_MENU}<sup>*</sup></td>
</tr>
<tr>
<td>Same as Android <em>Back</em></td>
- <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_B BUTTON_B}<sup>*</sup> and
-{@link android.view.KeyEvent#KEYCODE_BACK KEYCODE_BACK}</td>
+ <td>{@link android.view.KeyEvent#KEYCODE_BACK KEYCODE_BACK}</td>
+ </tr>
+ <tr>
+ <td>Navigate back to a previous item in a menu</td>
+ <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_B BUTTON_B}<sup>**</sup></td>
</tr>
<tr>
<td>Confirm selection, or perform primary game action</td>
- <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_A BUTTON_A}<sup>*</sup> and
+ <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_A BUTTON_A}<sup>**</sup> and
{@link android.view.KeyEvent#KEYCODE_DPAD_CENTER DPAD_CENTER}</td>
</tr>
</table>
<p>
-<em>* This could be the opposite button (A/B), depending on the locale that
+<em>* Your game should not rely on the presence of the Start, Select, or Menu
+ buttons.</em>
+</p>
+<p>
+<em>** This could be the opposite button (A/B), depending on the locale that
you are supporting.</em>
</p>
diff --git a/docs/html/training/notify-user/display-progress.jd b/docs/html/training/notify-user/display-progress.jd
index 2b2b3ae7b75d..c00576cad393 100644
--- a/docs/html/training/notify-user/display-progress.jd
+++ b/docs/html/training/notify-user/display-progress.jd
@@ -80,6 +80,7 @@ previous.link=expanded.html
setProgress(0, 0, false)}. For example:
</p>
<pre>
+int id = 1;
...
mNotifyManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@@ -100,7 +101,7 @@ new Thread(
// state
mBuilder.setProgress(100, incr, false);
// Displays the progress bar for the first time.
- mNotifyManager.notify(0, mBuilder.build());
+ mNotifyManager.notify(id, mBuilder.build());
// Sleeps the thread, simulating an operation
// that takes time
try {
@@ -114,7 +115,7 @@ new Thread(
mBuilder.setContentText("Download complete")
// Removes the progress bar
.setProgress(0,0,false);
- mNotifyManager.notify(ID, mBuilder.build());
+ mNotifyManager.notify(id, mBuilder.build());
}
}
// Starts the thread by calling the run() method in its Runnable
@@ -157,7 +158,7 @@ new Thread(
// percentage, and "determinate" state
mBuilder.setProgress(100, incr, false);
// Issues the notification
-mNotifyManager.notify(0, mBuilder.build());
+mNotifyManager.notify(id, mBuilder.build());
</pre>
<p>
Replace the lines you've found with the following lines. Notice that the third parameter
@@ -169,7 +170,7 @@ mNotifyManager.notify(0, mBuilder.build());
// Sets an activity indicator for an operation of indeterminate length
mBuilder.setProgress(0, 0, true);
// Issues the notification
-mNotifyManager.notify(0, mBuilder.build());
+mNotifyManager.notify(id, mBuilder.build());
</pre>
<p>
The resulting indicator is shown in figure 2:
diff --git a/docs/html/training/notify-user/navigation.jd b/docs/html/training/notify-user/navigation.jd
index ac4689aa1286..fc95013145ac 100644
--- a/docs/html/training/notify-user/navigation.jd
+++ b/docs/html/training/notify-user/navigation.jd
@@ -95,6 +95,7 @@ next.link=managing.html
{@link android.app.Activity}. For example:
</p>
<pre>
+int id = 1;
...
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index c8bcf2680d9a..66bf75c4fdac 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -352,13 +352,19 @@ public class Matrix {
}
/**
- * Set the matrix to the concatenation of the two specified matrices,
- * returning true if the the result can be represented. Either of the two
- * matrices may also be the target matrix. this = a * b
+ * Set the matrix to the concatenation of the two specified matrices and
+ * return true.
+ *
+ * <p>Either of the two matrices may also be the target matrix, that is
+ * <code>matrixA.setConcat(matrixA, matrixB);</code> is valid.</p>
+ *
+ * <p class="note">In {@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1} and below, this
+ * function returns true only if the result can be represented. In
+ * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and above, it always returns true.</p>
*/
public boolean setConcat(Matrix a, Matrix b) {
- return native_setConcat(native_instance, a.native_instance,
- b.native_instance);
+ native_setConcat(native_instance, a.native_instance, b.native_instance);
+ return true;
}
/**
@@ -366,7 +372,8 @@ public class Matrix {
* M' = M * T(dx, dy)
*/
public boolean preTranslate(float dx, float dy) {
- return native_preTranslate(native_instance, dx, dy);
+ native_preTranslate(native_instance, dx, dy);
+ return true;
}
/**
@@ -374,7 +381,8 @@ public class Matrix {
* M' = M * S(sx, sy, px, py)
*/
public boolean preScale(float sx, float sy, float px, float py) {
- return native_preScale(native_instance, sx, sy, px, py);
+ native_preScale(native_instance, sx, sy, px, py);
+ return true;
}
/**
@@ -382,7 +390,8 @@ public class Matrix {
* M' = M * S(sx, sy)
*/
public boolean preScale(float sx, float sy) {
- return native_preScale(native_instance, sx, sy);
+ native_preScale(native_instance, sx, sy);
+ return true;
}
/**
@@ -390,7 +399,8 @@ public class Matrix {
* M' = M * R(degrees, px, py)
*/
public boolean preRotate(float degrees, float px, float py) {
- return native_preRotate(native_instance, degrees, px, py);
+ native_preRotate(native_instance, degrees, px, py);
+ return true;
}
/**
@@ -398,7 +408,8 @@ public class Matrix {
* M' = M * R(degrees)
*/
public boolean preRotate(float degrees) {
- return native_preRotate(native_instance, degrees);
+ native_preRotate(native_instance, degrees);
+ return true;
}
/**
@@ -406,7 +417,8 @@ public class Matrix {
* M' = M * K(kx, ky, px, py)
*/
public boolean preSkew(float kx, float ky, float px, float py) {
- return native_preSkew(native_instance, kx, ky, px, py);
+ native_preSkew(native_instance, kx, ky, px, py);
+ return true;
}
/**
@@ -414,7 +426,8 @@ public class Matrix {
* M' = M * K(kx, ky)
*/
public boolean preSkew(float kx, float ky) {
- return native_preSkew(native_instance, kx, ky);
+ native_preSkew(native_instance, kx, ky);
+ return true;
}
/**
@@ -422,7 +435,8 @@ public class Matrix {
* M' = M * other
*/
public boolean preConcat(Matrix other) {
- return native_preConcat(native_instance, other.native_instance);
+ native_preConcat(native_instance, other.native_instance);
+ return true;
}
/**
@@ -430,7 +444,8 @@ public class Matrix {
* M' = T(dx, dy) * M
*/
public boolean postTranslate(float dx, float dy) {
- return native_postTranslate(native_instance, dx, dy);
+ native_postTranslate(native_instance, dx, dy);
+ return true;
}
/**
@@ -438,7 +453,8 @@ public class Matrix {
* M' = S(sx, sy, px, py) * M
*/
public boolean postScale(float sx, float sy, float px, float py) {
- return native_postScale(native_instance, sx, sy, px, py);
+ native_postScale(native_instance, sx, sy, px, py);
+ return true;
}
/**
@@ -446,7 +462,8 @@ public class Matrix {
* M' = S(sx, sy) * M
*/
public boolean postScale(float sx, float sy) {
- return native_postScale(native_instance, sx, sy);
+ native_postScale(native_instance, sx, sy);
+ return true;
}
/**
@@ -454,7 +471,8 @@ public class Matrix {
* M' = R(degrees, px, py) * M
*/
public boolean postRotate(float degrees, float px, float py) {
- return native_postRotate(native_instance, degrees, px, py);
+ native_postRotate(native_instance, degrees, px, py);
+ return true;
}
/**
@@ -462,7 +480,8 @@ public class Matrix {
* M' = R(degrees) * M
*/
public boolean postRotate(float degrees) {
- return native_postRotate(native_instance, degrees);
+ native_postRotate(native_instance, degrees);
+ return true;
}
/**
@@ -470,7 +489,8 @@ public class Matrix {
* M' = K(kx, ky, px, py) * M
*/
public boolean postSkew(float kx, float ky, float px, float py) {
- return native_postSkew(native_instance, kx, ky, px, py);
+ native_postSkew(native_instance, kx, ky, px, py);
+ return true;
}
/**
@@ -478,7 +498,8 @@ public class Matrix {
* M' = K(kx, ky) * M
*/
public boolean postSkew(float kx, float ky) {
- return native_postSkew(native_instance, kx, ky);
+ native_postSkew(native_instance, kx, ky);
+ return true;
}
/**
@@ -486,7 +507,8 @@ public class Matrix {
* M' = other * M
*/
public boolean postConcat(Matrix other) {
- return native_postConcat(native_instance, other.native_instance);
+ native_postConcat(native_instance, other.native_instance);
+ return true;
}
/** Controlls how the src rect should align into the dst rect for
@@ -828,41 +850,41 @@ public class Matrix {
float kx, float ky, float px, float py);
private static native void native_setSkew(long native_object,
float kx, float ky);
- private static native boolean native_setConcat(long native_object,
- long native_a,
- long native_b);
- private static native boolean native_preTranslate(long native_object,
- float dx, float dy);
- private static native boolean native_preScale(long native_object,
- float sx, float sy, float px, float py);
- private static native boolean native_preScale(long native_object,
- float sx, float sy);
- private static native boolean native_preRotate(long native_object,
- float degrees, float px, float py);
- private static native boolean native_preRotate(long native_object,
- float degrees);
- private static native boolean native_preSkew(long native_object,
- float kx, float ky, float px, float py);
- private static native boolean native_preSkew(long native_object,
- float kx, float ky);
- private static native boolean native_preConcat(long native_object,
- long native_other_matrix);
- private static native boolean native_postTranslate(long native_object,
- float dx, float dy);
- private static native boolean native_postScale(long native_object,
- float sx, float sy, float px, float py);
- private static native boolean native_postScale(long native_object,
- float sx, float sy);
- private static native boolean native_postRotate(long native_object,
- float degrees, float px, float py);
- private static native boolean native_postRotate(long native_object,
- float degrees);
- private static native boolean native_postSkew(long native_object,
- float kx, float ky, float px, float py);
- private static native boolean native_postSkew(long native_object,
- float kx, float ky);
- private static native boolean native_postConcat(long native_object,
- long native_other_matrix);
+ private static native void native_setConcat(long native_object,
+ long native_a,
+ long native_b);
+ private static native void native_preTranslate(long native_object,
+ float dx, float dy);
+ private static native void native_preScale(long native_object,
+ float sx, float sy, float px, float py);
+ private static native void native_preScale(long native_object,
+ float sx, float sy);
+ private static native void native_preRotate(long native_object,
+ float degrees, float px, float py);
+ private static native void native_preRotate(long native_object,
+ float degrees);
+ private static native void native_preSkew(long native_object,
+ float kx, float ky, float px, float py);
+ private static native void native_preSkew(long native_object,
+ float kx, float ky);
+ private static native void native_preConcat(long native_object,
+ long native_other_matrix);
+ private static native void native_postTranslate(long native_object,
+ float dx, float dy);
+ private static native void native_postScale(long native_object,
+ float sx, float sy, float px, float py);
+ private static native void native_postScale(long native_object,
+ float sx, float sy);
+ private static native void native_postRotate(long native_object,
+ float degrees, float px, float py);
+ private static native void native_postRotate(long native_object,
+ float degrees);
+ private static native void native_postSkew(long native_object,
+ float kx, float ky, float px, float py);
+ private static native void native_postSkew(long native_object,
+ float kx, float ky);
+ private static native void native_postConcat(long native_object,
+ long native_other_matrix);
private static native boolean native_setRectToRect(long native_object,
RectF src, RectF dst, int stf);
private static native boolean native_setPolyToPoly(long native_object,
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index 64de95fabc20..16415114cc3b 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -485,7 +485,10 @@ public class TouchFeedbackDrawable extends LayerDrawable {
} else if (state == null) {
ns = new TouchFeedbackState(null, this, res);
} else {
- ns = state;
+ // We always need a new state since child drawables contain local
+ // state but live within the parent's constant state.
+ // TODO: Move child drawables into local state.
+ ns = new TouchFeedbackState(state, this, res);
}
if (res != null) {
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 33683ab9f82c..d6f75ba8f9c4 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -14,7 +14,6 @@
package android.graphics.drawable;
-import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.res.Resources;
@@ -28,11 +27,7 @@ import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.Region;
-import android.location.Address;
-import android.net.ParseException;
-import android.sax.StartElementListener;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
@@ -47,7 +42,6 @@ import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -157,8 +151,8 @@ import java.util.HashSet;
* </dd>
*/
public class VectorDrawable extends Drawable {
- private static final String LOGTAG = "VectorDrawable";
- public static final int INFINITE = ValueAnimator.INFINITE;
+ private static final String LOGTAG = VectorDrawable.class.getSimpleName();
+
private static final String SHAPE_SIZE = "size";
private static final String SHAPE_VIEWPORT = "viewport";
private static final String SHAPE_GROUP = "group";
@@ -170,23 +164,32 @@ public class VectorDrawable extends Drawable {
private static final int LINECAP_BUTT = 0;
private static final int LINECAP_ROUND = 1;
private static final int LINECAP_SQUARE = 2;
+
private static final int LINEJOIN_MITER = 0;
private static final int LINEJOIN_ROUND = 1;
private static final int LINEJOIN_BEVEL = 2;
+
private static final int DEFAULT_DURATION = 1000;
private static final long DEFAULT_INFINITE_DURATION = 60 * 60 * 1000;
+
private VectorDrawableState mVectorState;
private int mAlpha = 0xFF;
public VectorDrawable() {
- mVectorState = new VectorDrawableState();
+ mVectorState = new VectorDrawableState(null);
mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+
setDuration(DEFAULT_DURATION);
}
- private VectorDrawable(VectorDrawableState state) {
+ private VectorDrawable(VectorDrawableState state, Resources res, Theme theme) {
mVectorState = new VectorDrawableState(state);
mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+
+ if (theme != null && canApplyTheme()) {
+ applyTheme(theme);
+ }
+
long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
if (duration == -1) { // if it set to infinite set to 1 hour
duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
@@ -197,6 +200,7 @@ public class VectorDrawable extends Drawable {
}
final static class VectorDrawableState extends ConstantState {
+ int[] mThemeAttrs;
int mChangingConfigurations;
ValueAnimator mBasicAnimator;
VAnimatedPath mVAnimatedPath = new VAnimatedPath();
@@ -204,20 +208,29 @@ public class VectorDrawable extends Drawable {
int mIntrinsicHeight;
int mIntrinsicWidth;
- public VectorDrawableState(){
+ public VectorDrawableState(VectorDrawableState copy) {
+ if (copy != null) {
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
+ mPadding = new Rect(copy.mPadding);
+ mIntrinsicHeight = copy.mIntrinsicHeight;
+ mIntrinsicWidth = copy.mIntrinsicWidth;
+ }
}
- public VectorDrawableState(VectorDrawableState copy){
- mChangingConfigurations = copy.mChangingConfigurations;
- mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
- mPadding = new Rect(copy.mPadding);
- mIntrinsicHeight = copy.mIntrinsicHeight;
- mIntrinsicWidth = copy.mIntrinsicWidth;
+ @Override
+ public Drawable newDrawable() {
+ return new VectorDrawable(this, null, null);
}
@Override
- public Drawable newDrawable() {
- return new VectorDrawable(this);
+ public Drawable newDrawable(Resources res) {
+ return new VectorDrawable(this, res, null);
+ }
+
+ @Override
+ public Drawable newDrawable(Resources res, Theme theme) {
+ return new VectorDrawable(this, res, theme);
}
@Override
@@ -459,29 +472,49 @@ public class VectorDrawable extends Drawable {
@Override
public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- setAnimatedPath(inflateInternal(res, parser, attrs));
+ final VAnimatedPath p = inflateInternal(res, parser, attrs, theme);
+ setAnimatedPath(p);
}
- private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs)
- throws XmlPullParserException, IOException {
+ @Override
+ public boolean canApplyTheme() {
+ return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme();
+ }
+
+ @Override
+ public void applyTheme(Theme t) {
+ super.applyTheme(t);
+
+ final VectorDrawableState state = mVectorState;
+ final VAnimatedPath path = state.mVAnimatedPath;
+ if (path != null && path.canApplyTheme()) {
+ path.applyTheme(t);
+ }
+ }
+
+ private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
+ final VAnimatedPath animatedPath = new VAnimatedPath();
+
boolean noSizeTag = true;
boolean noViewportTag = true;
boolean noGroupTag = true;
boolean noPathTag = true;
- final VAnimatedPath animatedPath = new VAnimatedPath();
- VectorDrawable.VGroup currentGroup = null;
+
+ VGroup currentGroup = null;
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
- String tagName = parser.getName();
+ final String tagName = parser.getName();
if (SHAPE_PATH.equals(tagName)) {
- VectorDrawable.VPath p = new VPath(res, attrs);
- currentGroup.add(p);
+ final VPath path = new VPath();
+ path.inflate(res, attrs, theme);
+ currentGroup.add(path);
noPathTag = false;
} else if (SHAPE_ANIMATION.equals(tagName)) {
- VectorDrawable.VAnimation anim =
- new VAnimation(res, attrs, animatedPath.mGroupList);
+ final VAnimation anim = new VAnimation();
+ anim.inflate(animatedPath.mGroupList, res, attrs, theme);
animatedPath.addAnimation(anim);
} else if (SHAPE_SIZE.equals(tagName)) {
animatedPath.parseSize(res, attrs);
@@ -490,17 +523,17 @@ public class VectorDrawable extends Drawable {
animatedPath.parseViewport(res, attrs);
noViewportTag = false;
} else if (SHAPE_GROUP.equals(tagName)) {
- currentGroup = new VectorDrawable.VGroup();
+ currentGroup = new VGroup();
animatedPath.mGroupList.add(currentGroup);
noGroupTag = false;
} else if (SHAPE_VECTOR.equals(tagName)) {
- TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable);
+ final TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable);
animatedPath.setTrigger(a.getInteger(R.styleable.VectorDrawable_trigger, 0));
// Parsing the version information.
// Right now, we only support version "1".
// If the xml didn't specify the version number, the default version is "1".
- int versionCode = a.getInt(R.styleable.VectorDrawable_versionCode, 1);
+ final int versionCode = a.getInt(R.styleable.VectorDrawable_versionCode, 1);
if (versionCode != 1) {
throw new IllegalArgumentException(
"So far, VectorDrawable only support version 1");
@@ -509,33 +542,41 @@ public class VectorDrawable extends Drawable {
a.recycle();
}
}
+
eventType = parser.next();
}
+
if (noSizeTag || noViewportTag || noGroupTag || noPathTag) {
- StringBuffer tag = new StringBuffer();
+ final StringBuffer tag = new StringBuffer();
+
if (noSizeTag) {
- tag.append("size");
+ tag.append(SHAPE_SIZE);
}
+
if (noViewportTag){
if (tag.length()>0) {
tag.append(" & ");
}
- tag.append("size");
+ tag.append(SHAPE_SIZE);
}
+
if (noGroupTag){
if (tag.length()>0) {
tag.append(" & ");
}
- tag.append("group");
+ tag.append(SHAPE_GROUP);
}
+
if (noPathTag){
if (tag.length()>0) {
tag.append(" or ");
}
- tag.append("path");
+ tag.append(SHAPE_PATH);
}
- throw new XmlPullParserException("no "+tag+" defined");
+
+ throw new XmlPullParserException("no " + tag + " defined");
}
+
// post parse cleanup
animatedPath.parseFinish();
return animatedPath;
@@ -543,16 +584,18 @@ public class VectorDrawable extends Drawable {
private void setAnimatedPath(VAnimatedPath animatedPath) {
mVectorState.mVAnimatedPath = animatedPath;
+
setIntrinsicWidth((int) mVectorState.mVAnimatedPath.mBaseWidth);
setIntrinsicHeight((int) mVectorState.mVAnimatedPath.mBaseHeight);
+
long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
if (duration == -1) { // if it set to infinite set to 1 hour
duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
}
- setDuration(duration);
+ setDuration(duration);
setAnimationFraction(0);
}
@@ -570,8 +613,6 @@ public class VectorDrawable extends Drawable {
}
private static class VAnimatedPath {
- private static final String LOGTAG = "VAnimatedPath";
-
private ArrayList<VAnimation> mCurrentAnimList = null;
private VPath[] mCurrentPaths;
private float mAnimationValue = 0; // value goes from 0 to 1
@@ -585,7 +626,9 @@ public class VectorDrawable extends Drawable {
private int[] mCurrentState = new int[0];
private int mTrigger;
private boolean mTriggerState;
- ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
+
+ final ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
+
float mBaseWidth = 1;
float mBaseHeight = 1;
float mViewportWidth;
@@ -594,10 +637,11 @@ public class VectorDrawable extends Drawable {
public VAnimatedPath() {
setup();
}
+
public VAnimatedPath(VAnimatedPath copy) {
setup();
mCurrentAnimList = new ArrayList<VAnimation>(copy.mCurrentAnimList);
- mGroupList = new ArrayList<VGroup>(copy.mGroupList);
+ mGroupList.addAll(copy.mGroupList);
if (copy.mCurrentPaths != null) {
mCurrentPaths = new VPath[copy.mCurrentPaths.length];
for (int i = 0; i < mCurrentPaths.length; i++) {
@@ -615,8 +659,53 @@ public class VectorDrawable extends Drawable {
mCurrentState = new int[0];
}
+ public boolean canApplyTheme() {
+ final ArrayList<VGroup> groups = mGroupList;
+ for (int i = groups.size() - 1; i >= 0; i--) {
+ final ArrayList<VPath> paths = groups.get(i).mVGList;
+ for (int j = paths.size() - 1; j >= 0; j--) {
+ final VPath path = paths.get(j);
+ if (path.canApplyTheme()) {
+ return true;
+ }
+ }
+ }
+
+ final ArrayList<VAnimation> anims = mCurrentAnimList;
+ for (int i = anims.size() - 1; i >= 0; i--) {
+ final VAnimation anim = anims.get(i);
+ if (anim.canApplyTheme()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void applyTheme(Theme t) {
+ final ArrayList<VGroup> groups = mGroupList;
+ for (int i = groups.size() - 1; i >= 0; i--) {
+ final ArrayList<VPath> paths = groups.get(i).mVGList;
+ for (int j = paths.size() - 1; j >= 0; j--) {
+ final VPath path = paths.get(j);
+ if (path.canApplyTheme()) {
+ path.applyTheme(t);
+ }
+ }
+ }
+
+ final ArrayList<VAnimation> anims = mCurrentAnimList;
+ for (int i = anims.size() - 1; i >= 0; i--) {
+ final VAnimation anim = anims.get(i);
+ if (anim.canApplyTheme()) {
+ anim.applyTheme(t);
+ }
+ }
+ }
+
public void setTrigger(int trigger){
- int []lut = { 0,
+ final int [] lut = {
+ 0,
R.attr.state_pressed,
R.attr.state_focused,
R.attr.state_hovered,
@@ -626,6 +715,7 @@ public class VectorDrawable extends Drawable {
R.attr.state_activated,
R.attr.state_focused
};
+
mTrigger = lut[trigger];
}
@@ -663,23 +753,27 @@ public class VectorDrawable extends Drawable {
* @return true if you need to keep repeating
*/
public boolean setAnimationFraction(float value) {
- int len = mCurrentPaths.length;
getTotalAnimationDuration();
+
long animationTime = (long) (value * mTotalDuration);
+ final int len = mCurrentPaths.length;
for (int i = 0; i < len; i++) {
- VPath path = mCurrentPaths[i];
animationTime =
(long) ((mTotalDuration == -1) ? value * 1000 : mTotalDuration * value);
- int size = mCurrentAnimList.size();
+
+ final VPath path = mCurrentPaths[i];
+ final int size = mCurrentAnimList.size();
for (int j = 0; j < size; j++) {
- VAnimation vAnimation = mCurrentAnimList.get(j);
+ final VAnimation vAnimation = mCurrentAnimList.get(j);
if (vAnimation.doesAdjustPath(path)) {
mCurrentPaths[i] = vAnimation.getPathAtTime(animationTime, path);
}
}
}
- this.mAnimationValue = value;
+
+ mAnimationValue = value;
+
if (mTotalDuration == -1) {
return true;
} else {
@@ -688,16 +782,15 @@ public class VectorDrawable extends Drawable {
}
public void draw(Canvas canvas) {
- int w = canvas.getWidth();
- int h = canvas.getHeight();
- float scale = w / mViewportWidth;
- scale = Math.min(h / mViewportHeight, scale);
-
if (mCurrentPaths == null) {
Log.e(LOGTAG,"mCurrentPaths == null");
return;
}
+ // TODO: This should probably use getBounds().
+ final int w = canvas.getWidth();
+ final int h = canvas.getHeight();
+
for (int i = 0; i < mCurrentPaths.length; i++) {
if (mCurrentPaths[i] != null && mCurrentPaths[i].isVisible(mCurrentState)) {
drawPath(mCurrentPaths[i], canvas, w, h);
@@ -706,8 +799,7 @@ public class VectorDrawable extends Drawable {
}
private void drawPath(VPath vPath, Canvas canvas, int w, int h) {
- float scale = w / mViewportWidth;
- scale = Math.min(h / mViewportHeight, scale);
+ final float scale = Math.min(h / mViewportHeight, w / mViewportWidth);
vPath.toPath(mPath);
Path path = mPath;
@@ -746,12 +838,14 @@ public class VectorDrawable extends Drawable {
if (vPath.mClip) {
canvas.clipPath(mRenderPath, Region.Op.REPLACE);
}
+
if (vPath.mFillColor != 0) {
mFillPaint.setColor(vPath.mFillColor);
int alpha = 0xFF & (vPath.mFillColor >> 24);
mFillPaint.setAlpha(alpha);
canvas.drawPath(mRenderPath, mFillPaint);
}
+
if (vPath.mStrokeColor != 0) {
if (vPath.mStrokelineJoin != null) {
mStrokePaint.setStrokeJoin(vPath.mStrokelineJoin);
@@ -773,7 +867,7 @@ public class VectorDrawable extends Drawable {
* TODO: improve memory use & performance or move to C++
*/
public void parseFinish() {
- HashMap<String, VAnimation> newAnimations = new HashMap<String, VAnimation>();
+ final HashMap<String, VAnimation> newAnimations = new HashMap<String, VAnimation>();
for (VGroup group : mGroupList) {
for (VPath vPath : group.getPaths()) {
if (!vPath.mAnimated) {
@@ -784,16 +878,19 @@ public class VectorDrawable extends Drawable {
} else {
ap = newAnimations.get(vPath.getID());
}
+
ap.addPath(vPath);
vPath.mAnimated = true;
}
}
}
+
if (mCurrentAnimList == null) {
mCurrentAnimList = new ArrayList<VectorDrawable.VAnimation>();
}
mCurrentAnimList.addAll(newAnimations.values());
- Collection<VPath> paths = mGroupList.get(0).getPaths();
+
+ final Collection<VPath> paths = mGroupList.get(0).getPaths();
mCurrentPaths = paths.toArray(new VPath[paths.size()]);
for (int i = 0; i < mCurrentPaths.length; i++) {
mCurrentPaths[i] = new VPath(mCurrentPaths[i]);
@@ -854,40 +951,41 @@ public class VectorDrawable extends Drawable {
}
private static class VAnimation {
- private static final String LOGTAG = "VAnimation";
+ private final static int DIRECTION_FORWARD = 0;
+ private final static int DIRECTION_IN_AND_OUT = 1;
+
private VPath[] mPaths = new VPath[0];
public enum Style {
INTERPOLATE, CROSSFADE, WIPE
}
+
Interpolator mAnimInterpolator = new AccelerateDecelerateInterpolator();
+
+ private int[] mThemeAttrs;
private Style mStyle;
private int mLimitProperty = 0;
private long[] mDuration = {DEFAULT_DURATION};
private long mStartOffset;
private long mRepeat = 1;
- private HashSet<String>mSeqMap = new HashSet<String>();
+ private HashSet<String> mSeqMap = new HashSet<String>();
private long mWipeDirection;
private int mMode = 0; // forward = 0 inAndOut = 1;
private int mInterpolatorType;
private String mId;
- private final static int DIRECTION_FORWARD = 0;
- private final static int DIRECTION_IN_AND_OUT = 1;
public VAnimation() {
+ // Empty constructor.
}
- public boolean doesAdjustPath(VPath path) {
- return mSeqMap.contains(path.getID());
- }
-
- public VAnimation(Resources r, AttributeSet attrs, ArrayList<VGroup> groups)
+ public void inflate(ArrayList<VGroup> groups, Resources r, AttributeSet attrs, Theme theme)
throws XmlPullParserException {
String value;
String[] sp;
int name;
- TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableAnimation);
+ final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableAnimation);
+ mThemeAttrs = a.extractThemeAttrs();
value = a.getString(R.styleable.VectorDrawableAnimation_sequence);
if (value != null) {
@@ -910,28 +1008,42 @@ public class VectorDrawable extends Drawable {
if (value != null) {
long totalDuration = 0;
sp = value.split(",");
- long[] dur = new long[sp.length];
+
+ final long[] dur = new long[sp.length];
for (int j = 0; j < dur.length; j++) {
dur[j] = Long.parseLong(sp[j]);
totalDuration += dur[j];
}
+
if (totalDuration == 0){
throw new XmlPullParserException(a.getPositionDescription()+
"total duration must not be zero");
}
+
setDuration(dur);
}
setRepeat(a.getInt(R.styleable.VectorDrawableAnimation_repeatCount, 1));
-
setStartOffset(a.getInt(R.styleable.VectorDrawableAnimation_startDelay, 0));
-
setMode(a.getInt(R.styleable.VectorDrawableAnimation_repeatStyle, 0));
fixMissingParameters();
+
a.recycle();
}
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null;
+ }
+
+ public void applyTheme(Theme t) {
+ // TODO: Apply theme.
+ }
+
+ public boolean doesAdjustPath(VPath path) {
+ return mSeqMap.contains(path.getID());
+ }
+
public String getId() {
if (mId == null) {
mId = mPaths[0].getID();
@@ -1031,7 +1143,7 @@ public class VectorDrawable extends Drawable {
}
public void setPaths(VPath[] paths) {
- this.mPaths = paths;
+ mPaths = paths;
}
public void addPath(VPath path) {
@@ -1049,7 +1161,7 @@ public class VectorDrawable extends Drawable {
}
public void interpolate(VPath p1, VPath p2, float time, VPath dest) {
- dest.interpolate(time, p1, p2, dest, mLimitProperty);
+ VPath.interpolate(time, p1, p2, dest, mLimitProperty);
}
public VPath getPathAtTime(long milliseconds, VPath dest) {
@@ -1150,8 +1262,8 @@ public class VectorDrawable extends Drawable {
}
private static class VGroup {
- private HashMap<String, VPath> mVGPathMap = new HashMap<String, VPath>();
- private ArrayList<VPath> mVGList = new ArrayList<VPath>();
+ private final HashMap<String, VPath> mVGPathMap = new HashMap<String, VPath>();
+ private final ArrayList<VPath> mVGList = new ArrayList<VPath>();
public void add(VPath path) {
String id = path.getID();
@@ -1183,34 +1295,52 @@ public class VectorDrawable extends Drawable {
private static final int LIMIT_TRIM_PATH_START = 3;
private static final int LIMIT_TRIM_PATH_OFFSET = 5;
private static final int LIMIT_TRIM_PATH_END = 4;
+
private static final int STATE_UNDEFINED=0;
private static final int STATE_TRUE=1;
private static final int STATE_FALSE=2;
+
private static final int MAX_STATES = 10;
- private VNode[] mNode = null;
- private String mId;
+
+ private int[] mThemeAttrs;
+
int mStrokeColor = 0;
float mStrokeWidth = 0;
float mStrokeOpacity = Float.NaN;
+
int mFillColor = 0;
int mFillRule;
float mFillOpacity = Float.NaN;
+
float mRotate = 0;
float mPivotX = 0;
float mPivotY = 0;
+
float mTrimPathStart = 0;
float mTrimPathEnd = 1;
float mTrimPathOffset = 0;
+
boolean mAnimated = false;
boolean mClip = false;
- public Paint.Cap mStrokelineCap = null;
- public Paint.Join mStrokelineJoin = null;
+ Paint.Cap mStrokelineCap = null;
+ Paint.Join mStrokelineJoin = null;
float mStrokeMiterlimit = 4;
+
+ private VNode[] mNode = null;
+ private String mId;
private int[] mCheckState = new int[MAX_STATES];
private boolean[] mCheckValue = new boolean[MAX_STATES];
private int mNumberOfStates = 0;
private int mNumberOfTrue = 0;
+ public VPath() {
+ // Empty constructor.
+ }
+
+ public VPath(VPath p) {
+ copyFrom(p);
+ }
+
public void addStateFilter(int state, boolean condition) {
int k = 0;
while (k < mNumberOfStates) {
@@ -1228,7 +1358,7 @@ public class VectorDrawable extends Drawable {
}
}
- int getState(int state){
+ private int getState(int state){
for (int i = 0; i < mNumberOfStates; i++) {
if (mCheckState[mNumberOfStates] == state){
return (mCheckValue[i])?STATE_TRUE:STATE_FALSE;
@@ -1250,34 +1380,33 @@ public class VectorDrawable extends Drawable {
}
}
- public VPath() {
- mId = this.toString(); // to ensure paths have unique names
- }
-
- public VPath(VPath p) {
- copyFrom(p);
- }
-
public String getID(){
return mId;
}
- public VPath(Resources r, AttributeSet attrs) {
- TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawablePath);
+ public void inflate(Resources r, AttributeSet attrs, Theme theme) {
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.VectorDrawablePath);
+ final int[] themeAttrs = a.extractThemeAttrs();
+ mThemeAttrs = themeAttrs;
+
mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, false);
mId = a.getString(R.styleable.VectorDrawablePath_name);
mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
- mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, 0);
- mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, Float.NaN);
- if (!Float.isNaN(mFillOpacity)) {
- mFillColor &= 0x00FFFFFF;
- mFillColor |= ((int) (0xFF * mFillOpacity)) << 24;
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_fill] == 0) {
+ mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, 0);
+ }
+
+ if (themeAttrs == null
+ || themeAttrs[R.styleable.VectorDrawablePath_fillOpacity] == 0) {
+ mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, Float.NaN);
}
+
mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, 0);
mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, 0);
mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, 0);
- int lineCap = a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, 0);
+
+ final int lineCap = a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, 0);
switch (lineCap) {
case LINECAP_BUTT:
mStrokelineCap = Paint.Cap.BUTT;
@@ -1289,7 +1418,8 @@ public class VectorDrawable extends Drawable {
mStrokelineCap = Paint.Cap.SQUARE;
break;
}
- int lineJoin = a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, 0);
+
+ final int lineJoin = a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, 0);
switch (lineJoin) {
case LINEJOIN_MITER:
mStrokelineJoin = Paint.Join.MITER;
@@ -1301,19 +1431,27 @@ public class VectorDrawable extends Drawable {
mStrokelineJoin = Paint.Join.BEVEL;
break;
}
+
mStrokeMiterlimit = a.getFloat(R.styleable.VectorDrawablePath_strokeMiterLimit,
mStrokeMiterlimit);
- mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
- mStrokeOpacity = a.getFloat(R.styleable.VectorDrawablePath_strokeOpacity, Float.NaN);
- if (!Float.isNaN(mStrokeOpacity)) {
- mStrokeColor &= 0x00FFFFFF;
- mStrokeColor |= ((int) (0xFF * mStrokeOpacity)) << 24;
+
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_stroke] == 0) {
+ mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
}
+
+ if (themeAttrs == null
+ || themeAttrs[R.styleable.VectorDrawablePath_strokeOpacity] == 0) {
+ mStrokeOpacity = a.getFloat(
+ R.styleable.VectorDrawablePath_strokeOpacity, Float.NaN);
+ }
+
mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, 0);
mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, 1);
mTrimPathOffset = a.getFloat(R.styleable.VectorDrawablePath_trimPathOffset, 0);
mTrimPathStart = a.getFloat(R.styleable.VectorDrawablePath_trimPathStart, 0);
- int[] states = {R.styleable.VectorDrawablePath_state_activated,
+
+ final int[] states = {
+ R.styleable.VectorDrawablePath_state_activated,
R.styleable.VectorDrawablePath_state_checkable,
R.styleable.VectorDrawablePath_state_checked,
R.styleable.VectorDrawablePath_state_enabled,
@@ -1321,15 +1459,66 @@ public class VectorDrawable extends Drawable {
R.styleable.VectorDrawablePath_state_hovered,
R.styleable.VectorDrawablePath_state_pressed,
R.styleable.VectorDrawablePath_state_selected,
- R.styleable.VectorDrawablePath_state_window_focused};
- for (int state : states) {
+ R.styleable.VectorDrawablePath_state_window_focused
+ };
+
+ final int N = states.length;
+ for (int i = 0; i < N; i++) {
+ final int state = states[i];
if (a.hasValue(state)) {
addStateFilter(state, a.getBoolean(state, false));
}
}
+
+ updateColorAlphas();
+
a.recycle();
}
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null;
+ }
+
+ public void applyTheme(Theme t) {
+ if (mThemeAttrs == null) {
+ return;
+ }
+
+ final TypedArray a = t.resolveAttributes(
+ mThemeAttrs, R.styleable.VectorDrawablePath, 0, 0);
+
+ if (a.hasValue(R.styleable.VectorDrawablePath_fill)) {
+ mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, 0);
+ }
+
+ if (a.hasValue(R.styleable.VectorDrawablePath_fillOpacity)) {
+ mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, Float.NaN);
+ }
+
+ if (a.hasValue(R.styleable.VectorDrawablePath_stroke)) {
+ mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
+ }
+
+ if (a.hasValue(R.styleable.VectorDrawablePath_strokeOpacity)) {
+ mStrokeOpacity = a.getFloat(
+ R.styleable.VectorDrawablePath_strokeOpacity, Float.NaN);
+ }
+
+ updateColorAlphas();
+ }
+
+ private void updateColorAlphas() {
+ if (!Float.isNaN(mFillOpacity)) {
+ mFillColor &= 0x00FFFFFF;
+ mFillColor |= ((int) (0xFF * mFillOpacity)) << 24;
+ }
+
+ if (!Float.isNaN(mStrokeOpacity)) {
+ mStrokeColor &= 0x00FFFFFF;
+ mStrokeColor |= ((int) (0xFF * mStrokeOpacity)) << 24;
+ }
+ }
+
private static int nextStart(String s, int end) {
char c;
@@ -1564,9 +1753,11 @@ public class VectorDrawable extends Drawable {
}
private static class VNode {
+ private static float[] current = new float[4];
+
char type;
float[] params;
- private static float[] current = new float[4];
+
public VNode(char type, float[] params) {
this.type = type;
this.params = params;
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 7cc10be872ac..4d8e512d1651 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1054,6 +1054,7 @@ struct ResTable_config
UI_MODE_TYPE_CAR = ACONFIGURATION_UI_MODE_TYPE_CAR,
UI_MODE_TYPE_TELEVISION = ACONFIGURATION_UI_MODE_TYPE_TELEVISION,
UI_MODE_TYPE_APPLIANCE = ACONFIGURATION_UI_MODE_TYPE_APPLIANCE,
+ UI_MODE_TYPE_WATCH = ACONFIGURATION_UI_MODE_TYPE_WATCH,
// uiMode bits for the night switch.
MASK_UI_MODE_NIGHT = 0x30,
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 7616ab0eafa6..098753bd5afa 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2557,6 +2557,9 @@ String8 ResTable_config::toString() const {
case ResTable_config::UI_MODE_TYPE_APPLIANCE:
res.append("appliance");
break;
+ case ResTable_config::UI_MODE_TYPE_WATCH:
+ res.append("watch");
+ break;
default:
res.appendFormat("uiModeType=%d",
dtohs(screenLayout&ResTable_config::MASK_UI_MODE_TYPE));
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 477d69172c78..df2123bb5db4 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -315,24 +315,15 @@ void Caches::clearGarbage() {
pathCache.clearGarbage();
patchCache.clearGarbage();
- Vector<RenderNode*> displayLists;
Vector<Layer*> layers;
{ // scope for the lock
Mutex::Autolock _l(mGarbageLock);
- displayLists = mDisplayListGarbage;
layers = mLayerGarbage;
- mDisplayListGarbage.clear();
mLayerGarbage.clear();
}
- size_t count = displayLists.size();
- for (size_t i = 0; i < count; i++) {
- RenderNode* displayList = displayLists.itemAt(i);
- delete displayList;
- }
-
- count = layers.size();
+ size_t count = layers.size();
for (size_t i = 0; i < count; i++) {
Layer* layer = layers.itemAt(i);
delete layer;
@@ -345,11 +336,6 @@ void Caches::deleteLayerDeferred(Layer* layer) {
mLayerGarbage.push(layer);
}
-void Caches::deleteDisplayListDeferred(RenderNode* displayList) {
- Mutex::Autolock _l(mGarbageLock);
- mDisplayListGarbage.push(displayList);
-}
-
void Caches::flush(FlushMode mode) {
FLUSH_LOGD("Flushing caches (mode %d)", mode);
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 50c5fef633d7..ba3ccafc2879 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -166,11 +166,6 @@ public:
*/
void deleteLayerDeferred(Layer* layer);
- /*
- * Can be used to delete a display list from a non EGL thread.
- */
- void deleteDisplayListDeferred(RenderNode* layer);
-
/**
* Binds the VBO used to render simple textured quads.
*/
@@ -420,7 +415,6 @@ private:
mutable Mutex mGarbageLock;
Vector<Layer*> mLayerGarbage;
- Vector<RenderNode*> mDisplayListGarbage;
DebugLevel mDebugLevel;
bool mInitialized;
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 5b4e03f515e0..ce711b65c9f9 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -68,13 +68,13 @@ bool DeferredLayerUpdater::apply() {
mLayer->setColorFilter(mColorFilter);
mLayer->setAlpha(mAlpha, mMode);
- if (mDisplayList) {
+ if (mDisplayList.get()) {
if (mWidth != mLayer->layer.getWidth() || mHeight != mLayer->layer.getHeight()) {
success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight);
}
mLayer->setBlend(mBlend);
mDisplayList->updateProperties();
- mLayer->updateDeferred(mDisplayList,
+ mLayer->updateDeferred(mDisplayList.get(),
mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
mDirtyRect.setEmpty();
mDisplayList = 0;
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 10fa264d87fe..ce08c2de8960 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -101,7 +101,7 @@ private:
// Layer type specific properties
// displayList and surfaceTexture are mutually exclusive, only 1 may be set
// dirtyRect is only valid if displayList is set
- RenderNode* mDisplayList;
+ sp<RenderNode> mDisplayList;
Rect mDirtyRect;
sp<GLConsumer> mSurfaceTexture;
SkMatrix* mTransform;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 9e6a96d38713..a5d8dcb3fe0f 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -29,6 +29,13 @@
namespace android {
namespace uirenderer {
+DisplayListData::DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {
+}
+
+DisplayListData::~DisplayListData() {
+ cleanupResources();
+}
+
void DisplayListData::cleanupResources() {
Caches& caches = Caches::getInstance();
caches.unregisterFunctors(functorCount);
@@ -91,5 +98,12 @@ void DisplayListData::cleanupResources() {
layers.clear();
}
+void DisplayListData::addChild(DrawDisplayListOp* op) {
+ LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawDisplayListOp with no render node!");
+
+ mChildren.push(op);
+ mReferenceHolders.push(op->renderNode());
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index df5cba61d7cb..fe70d13fb984 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -41,6 +41,7 @@
#include "Matrix.h"
#include "DeferredDisplayList.h"
#include "RenderProperties.h"
+#include "utils/VirtualLightRefBase.h"
class SkBitmap;
class SkPaint;
@@ -106,8 +107,8 @@ public:
*/
class DisplayListData {
public:
- DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {}
- virtual ~DisplayListData() { cleanupResources(); }
+ DisplayListData();
+ ~DisplayListData();
// allocator into which all ops were allocated
LinearAllocator allocator;
@@ -115,9 +116,6 @@ public:
// pointers to all ops within display list, pointing into allocator data
Vector<DisplayListOp*> displayListOps;
- // list of children display lists for quick, non-drawing traversal
- Vector<DrawDisplayListOp*> children;
-
// index of DisplayListOp restore, after which projected descendents should be drawn
int projectionReceiveIndex;
@@ -139,7 +137,15 @@ public:
return !displayListOps.size();
}
+ void addChild(DrawDisplayListOp* childOp);
+ const Vector<DrawDisplayListOp*>& children() { return mChildren; }
+
private:
+ Vector< sp<VirtualLightRefBase> > mReferenceHolders;
+
+ // list of children display lists for quick, non-drawing traversal
+ Vector<DrawDisplayListOp*> mChildren;
+
void cleanupResources();
};
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 5fa8f1d5e9ee..06f675efcf23 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1523,6 +1523,8 @@ public:
virtual const char* name() { return "DrawDisplayList"; }
+ RenderNode* renderNode() { return mDisplayList; }
+
private:
RenderNode* mDisplayList;
const int mFlags;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 78c97e14d363..a84aa6b690e1 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -191,7 +191,7 @@ status_t DisplayListRenderer::drawDisplayList(RenderNode* displayList,
DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList,
flags, *currentTransform());
addDrawOp(op);
- mDisplayListData->children.push(op);
+ mDisplayListData->addChild(op);
if (displayList->isProjectionReceiver()) {
mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size() - 1;
}
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 27409a2887c2..bfe4eda44ddc 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -140,6 +140,15 @@ void Layer::removeFbo(bool flush) {
}
}
+void Layer::updateDeferred(RenderNode* displayList,
+ int left, int top, int right, int bottom) {
+ requireRenderer();
+ this->displayList = displayList;
+ const Rect r(left, top, right, bottom);
+ dirtyRect.unionWith(r);
+ deferredUpdateScheduled = true;
+}
+
void Layer::setPaint(const SkPaint* paint) {
OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
setColorFilter((paint) ? paint->getColorFilter() : NULL);
@@ -244,7 +253,7 @@ void Layer::render() {
renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
!isBlend());
- renderer->drawDisplayList(displayList, dirtyRect, RenderNode::kReplayFlag_ClipChildren);
+ renderer->drawDisplayList(displayList.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren);
renderer->finish();
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index b428404f04e0..5375b4509db1 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -19,6 +19,7 @@
#include <cutils/compiler.h>
#include <sys/types.h>
+#include <utils/StrongPointer.h>
#include <GLES2/gl2.h>
@@ -85,13 +86,7 @@ public:
}
void updateDeferred(RenderNode* displayList,
- int left, int top, int right, int bottom) {
- requireRenderer();
- this->displayList = displayList;
- const Rect r(left, top, right, bottom);
- dirtyRect.unionWith(r);
- deferredUpdateScheduled = true;
- }
+ int left, int top, int right, int bottom);
inline uint32_t getWidth() const {
return texture.width;
@@ -294,7 +289,7 @@ public:
*/
bool deferredUpdateScheduled;
OpenGLRenderer* renderer;
- RenderNode* displayList;
+ sp<RenderNode> displayList;
Rect dirtyRect;
bool debugDrawUpdate;
bool hasDrawnSinceUpdate;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e1f484d90fd7..9dbcd36677fd 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -537,7 +537,7 @@ void OpenGLRenderer::countOverdraw() {
bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
if (layer->deferredUpdateScheduled && layer->renderer &&
- layer->displayList && layer->displayList->isRenderable()) {
+ layer->displayList.get() && layer->displayList->isRenderable()) {
ATRACE_CALL();
Rect& dirty = layer->dirtyRect;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 663b67ef053c..501007679308 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -59,17 +59,6 @@ RenderNode::~RenderNode() {
delete mDisplayListData;
}
-void RenderNode::destroyDisplayListDeferred(RenderNode* displayList) {
- if (displayList) {
- if (Caches::hasInstance()) {
- DISPLAY_LIST_LOGD("Deferring display list destruction");
- Caches::getInstance().deleteDisplayListDeferred(displayList);
- } else {
- delete displayList;
- }
- }
-}
-
void RenderNode::setData(DisplayListData* data) {
delete mDisplayListData;
mDisplayListData = data;
@@ -104,8 +93,8 @@ void RenderNode::updateProperties() {
}
if (mDisplayListData) {
- for (size_t i = 0; i < mDisplayListData->children.size(); i++) {
- RenderNode* childNode = mDisplayListData->children[i]->mDisplayList;
+ for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
+ RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList;
childNode->updateProperties();
}
}
@@ -118,8 +107,8 @@ bool RenderNode::hasFunctors() {
return true;
}
- for (size_t i = 0; i < mDisplayListData->children.size(); i++) {
- RenderNode* childNode = mDisplayListData->children[i]->mDisplayList;
+ for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
+ RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList;
if (childNode->hasFunctors()) {
return true;
}
@@ -248,8 +237,8 @@ void RenderNode::computeOrdering() {
// TODO: create temporary DDLOp and call computeOrderingImpl on top DisplayList so that
// transform properties are applied correctly to top level children
if (mDisplayListData == NULL) return;
- for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
- DrawDisplayListOp* childOp = mDisplayListData->children[i];
+ for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+ DrawDisplayListOp* childOp = mDisplayListData->children()[i];
childOp->mDisplayList->computeOrderingImpl(childOp,
&mProjectedNodes, &mat4::identity());
}
@@ -277,11 +266,11 @@ void RenderNode::computeOrderingImpl(
opState->mSkipInOrderDraw = false;
}
- if (mDisplayListData->children.size() > 0) {
+ if (mDisplayListData->children().size() > 0) {
const bool isProjectionReceiver = mDisplayListData->projectionReceiveIndex >= 0;
bool haveAppliedPropertiesToProjection = false;
- for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
- DrawDisplayListOp* childOp = mDisplayListData->children[i];
+ for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+ DrawDisplayListOp* childOp = mDisplayListData->children()[i];
RenderNode* child = childOp->mDisplayList;
Vector<DrawDisplayListOp*>* projectionChildren = NULL;
@@ -375,10 +364,10 @@ void RenderNode::replayNodeInParent(ReplayStateStruct& replayStruct, const int l
}
void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes) {
- if (mDisplayListData == NULL || mDisplayListData->children.size() == 0) return;
+ if (mDisplayListData == NULL || mDisplayListData->children().size() == 0) return;
- for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
- DrawDisplayListOp* childOp = mDisplayListData->children[i];
+ for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+ DrawDisplayListOp* childOp = mDisplayListData->children()[i];
RenderNode* child = childOp->mDisplayList;
float childZ = child->properties().getTranslationZ();
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index fb5336d1277c..fd0fabcffbbb 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -41,6 +41,7 @@
#include "DeferredDisplayList.h"
#include "DisplayList.h"
#include "RenderProperties.h"
+#include "utils/VirtualLightRefBase.h"
class SkBitmap;
class SkPaint;
@@ -76,7 +77,7 @@ class DrawDisplayListOp;
* recorded stream of canvas operations is refreshed. The DisplayList (and its properties) stay
* attached.
*/
-class RenderNode {
+class RenderNode : public VirtualLightRefBase {
public:
ANDROID_API RenderNode();
ANDROID_API ~RenderNode();
@@ -86,7 +87,6 @@ public:
kReplayFlag_ClipChildren = 0x1
};
- ANDROID_API static void destroyDisplayListDeferred(RenderNode* displayList);
ANDROID_API static void outputLogBuffer(int fd);
ANDROID_API void setData(DisplayListData* newData);
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 1e9089a30a46..7b509a2040a1 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -30,7 +30,19 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-DrawFrameTask::DrawFrameTask() : mContext(0), mRenderNode(0) {
+SetDisplayListData::SetDisplayListData() : mNewData(0) {}
+
+SetDisplayListData::SetDisplayListData(RenderNode* node, DisplayListData* newData)
+ : mTargetNode(node), mNewData(newData) {
+}
+
+SetDisplayListData::~SetDisplayListData() {}
+
+void SetDisplayListData::apply() const {
+ mTargetNode->setData(mNewData);
+}
+
+DrawFrameTask::DrawFrameTask() : mContext(0), mTaskMode(MODE_INVALID), mRenderNode(0) {
}
DrawFrameTask::~DrawFrameTask() {
@@ -41,13 +53,15 @@ void DrawFrameTask::setContext(CanvasContext* context) {
}
void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
- SetDisplayListData setter;
- setter.targetNode = renderNode;
- setter.newData = newData;
+ LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setDisplayListData with!");
+
+ SetDisplayListData setter(renderNode, newData);
mDisplayListDataUpdates.push(setter);
}
void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) {
+ LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!");
+
mLayers.push(layer);
}
@@ -61,6 +75,8 @@ void DrawFrameTask::removeLayer(DeferredLayerUpdater* layer) {
}
void DrawFrameTask::setRenderNode(RenderNode* renderNode) {
+ LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setRenderNode with!");
+
mRenderNode = renderNode;
}
@@ -69,37 +85,55 @@ void DrawFrameTask::setDirty(int left, int top, int right, int bottom) {
}
void DrawFrameTask::drawFrame(RenderThread* renderThread) {
- LOG_ALWAYS_FATAL_IF(!mRenderNode, "Cannot drawFrame with no render node!");
+ LOG_ALWAYS_FATAL_IF(!mRenderNode.get(), "Cannot drawFrame with no render node!");
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
- AutoMutex _lock(mLock);
- renderThread->queue(this);
- mSignal.wait(mLock);
+ postAndWait(renderThread, MODE_FULL);
// Reset the single-frame data
mDirty.setEmpty();
mRenderNode = 0;
}
+void DrawFrameTask::flushStateChanges(RenderThread* renderThread) {
+ LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
+
+ postAndWait(renderThread, MODE_STATE_ONLY);
+}
+
+void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) {
+ LOG_ALWAYS_FATAL_IF(mode == MODE_INVALID, "That's not a real mode, silly!");
+
+ mTaskMode = mode;
+ AutoMutex _lock(mLock);
+ renderThread->queue(this);
+ mSignal.wait(mLock);
+}
+
void DrawFrameTask::run() {
ATRACE_NAME("DrawFrame");
syncFrameState();
+ if (mTaskMode == MODE_STATE_ONLY) {
+ unblockUiThread();
+ return;
+ }
+
// Grab a copy of everything we need
Rect dirtyCopy(mDirty);
- RenderNode* renderNode = mRenderNode;
+ sp<RenderNode> renderNode = mRenderNode;
CanvasContext* context = mContext;
// This is temporary until WebView has a solution for syncing frame state
- bool canUnblockUiThread = !requiresSynchronousDraw(renderNode);
+ bool canUnblockUiThread = !requiresSynchronousDraw(renderNode.get());
// From this point on anything in "this" is *UNSAFE TO ACCESS*
if (canUnblockUiThread) {
unblockUiThread();
}
- drawRenderNode(context, renderNode, &dirtyCopy);
+ drawRenderNode(context, renderNode.get(), &dirtyCopy);
if (!canUnblockUiThread) {
unblockUiThread();
@@ -111,12 +145,16 @@ void DrawFrameTask::syncFrameState() {
for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) {
const SetDisplayListData& setter = mDisplayListDataUpdates[i];
- setter.targetNode->setData(setter.newData);
+ setter.apply();
}
mDisplayListDataUpdates.clear();
mContext->processLayerUpdates(&mLayers);
- mRenderNode->updateProperties();
+
+ // If we don't have an mRenderNode this is a state flush only
+ if (mRenderNode.get()) {
+ mRenderNode->updateProperties();
+ }
}
void DrawFrameTask::unblockUiThread() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 5450dd57133e..4e9b24487b47 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -18,6 +18,7 @@
#include <utils/Condition.h>
#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
#include <utils/Vector.h>
#include "RenderTask.h"
@@ -36,9 +37,16 @@ namespace renderthread {
class CanvasContext;
class RenderThread;
-struct SetDisplayListData {
- RenderNode* targetNode;
- DisplayListData* newData;
+class SetDisplayListData {
+public:
+ // This ctor exists for Vector's usage
+ SetDisplayListData();
+ SetDisplayListData(RenderNode* node, DisplayListData* newData);
+ ~SetDisplayListData();
+ void apply() const;
+private:
+ sp<RenderNode> mTargetNode;
+ DisplayListData* mNewData;
};
/*
@@ -61,10 +69,18 @@ public:
void setRenderNode(RenderNode* renderNode);
void setDirty(int left, int top, int right, int bottom);
void drawFrame(RenderThread* renderThread);
+ void flushStateChanges(RenderThread* renderThread);
virtual void run();
private:
+ enum TaskMode {
+ MODE_INVALID,
+ MODE_FULL,
+ MODE_STATE_ONLY,
+ };
+
+ void postAndWait(RenderThread* renderThread, TaskMode mode);
void syncFrameState();
void unblockUiThread();
static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty);
@@ -81,7 +97,8 @@ private:
/*********************************************
* Single frame data
*********************************************/
- RenderNode* mRenderNode;
+ TaskMode mTaskMode;
+ sp<RenderNode> mRenderNode;
Rect mDirty;
Vector<SetDisplayListData> mDisplayListDataUpdates;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 0b6be1983f48..43e653ca76ec 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -75,6 +75,9 @@ CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
void RenderProxy::destroyContext() {
if (mContext) {
+ // Flush any pending changes to ensure all garbage is destroyed
+ mDrawFrameTask.flushStateChanges(&mRenderThread);
+
SETUP_TASK(destroyContext);
args->context = mContext;
mContext = 0;
@@ -138,6 +141,10 @@ CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) {
}
void RenderProxy::destroyCanvas() {
+ // If the canvas is being destroyed we won't be drawing again anytime soon
+ // So flush any pending state changes to allow for resource cleanup.
+ mDrawFrameTask.flushStateChanges(&mRenderThread);
+
SETUP_TASK(destroyCanvas);
args->context = mContext;
post(task);
diff --git a/libs/hwui/utils/VirtualLightRefBase.h b/libs/hwui/utils/VirtualLightRefBase.h
new file mode 100644
index 000000000000..b545aabac802
--- /dev/null
+++ b/libs/hwui/utils/VirtualLightRefBase.h
@@ -0,0 +1,34 @@
+/*
+ * 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 VIRTUALLIGHTREFBASE_H
+#define VIRTUALLIGHTREFBASE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+namespace uirenderer {
+
+// This is a wrapper around LightRefBase that simply enforces a virtual
+// destructor to eliminate the template requirement of LightRefBase
+class VirtualLightRefBase : public LightRefBase<VirtualLightRefBase> {
+public:
+ virtual ~VirtualLightRefBase() {}
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* VIRTUALLIGHTREFBASE_H */
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 2667a720af67..3f6ccc9acdf8 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -402,7 +402,7 @@ void SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) {
uint32_t dirty;
if (icon.isValid()) {
- icon.bitmap.copyTo(&mLocked.state.icon.bitmap, SkBitmap::kARGB_8888_Config);
+ icon.bitmap.copyTo(&mLocked.state.icon.bitmap, kNative_8888_SkColorType);
if (!mLocked.state.icon.isValid()
|| mLocked.state.icon.hotSpotX != icon.hotSpotX
diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h
index 75e4843d38dc..797efd747066 100644
--- a/libs/input/SpriteController.h
+++ b/libs/input/SpriteController.h
@@ -65,7 +65,7 @@ struct SpriteIcon {
inline SpriteIcon copy() const {
SkBitmap bitmapCopy;
- bitmap.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config);
+ bitmap.copyTo(&bitmapCopy, kNative_8888_SkColorType);
return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY);
}
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 77ab17be35ac..77944c8ec34b 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -107,5 +107,10 @@
<!-- milliseconds before the heads up notification accepts touches. -->
<integer name="heads_up_sensitivity_delay">700</integer>
+
+ <!-- The min animation duration for animating views that are currently visible. -->
+ <integer name="recents_filter_animate_current_views_min_duration">175</integer>
+ <!-- The min animation duration for animating views that are newly visible. -->
+ <integer name="recents_filter_animate_new_views_min_duration">125</integer>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1c6d5ad0b98c..2c8f9a1612f9 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -236,6 +236,10 @@
<!-- The size of the activity icon in the recents task view. -->
<dimen name="recents_task_view_activity_icon_size">60dp</dimen>
+ <!-- Used to calculate the translation animation duration, the expected amount of movement
+ in dps over one second of time. -->
+ <dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen>
+
<!-- Space below the notification stack -->
<dimen name="notification_stack_margin_bottom">0dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index ab2ad966e97f..eb09335c9565 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -156,7 +156,7 @@ public class RecentTasksLoader implements View.OnTouchListener {
// Create an TaskDescription, returning null if the title or icon is null
TaskDescription createTaskDescription(int taskId, int persistentTaskId, Intent baseIntent,
- ComponentName origActivity, CharSequence description) {
+ ComponentName origActivity, CharSequence description, int userId) {
Intent intent = new Intent(baseIntent);
if (origActivity != null) {
intent.setComponent(origActivity);
@@ -175,7 +175,7 @@ public class RecentTasksLoader implements View.OnTouchListener {
TaskDescription item = new TaskDescription(taskId,
persistentTaskId, resolveInfo, baseIntent, info.packageName,
- description);
+ description, userId);
item.setLabel(title);
return item;
@@ -391,7 +391,8 @@ public class RecentTasksLoader implements View.OnTouchListener {
item = createTaskDescription(recentInfo.id,
recentInfo.persistentId, recentInfo.baseIntent,
- recentInfo.origActivity, recentInfo.description);
+ recentInfo.origActivity, recentInfo.description,
+ recentInfo.userId);
if (item != null) {
loadThumbnailAndIcon(item);
}
@@ -474,7 +475,8 @@ public class RecentTasksLoader implements View.OnTouchListener {
TaskDescription item = createTaskDescription(recentInfo.id,
recentInfo.persistentId, recentInfo.baseIntent,
- recentInfo.origActivity, recentInfo.description);
+ recentInfo.origActivity, recentInfo.description,
+ recentInfo.userId);
if (item != null) {
while (true) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index ef5604474baf..98bdee0c16ea 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -689,7 +689,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
if (DEBUG) Log.v(TAG, "Starting activity " + intent);
try {
context.startActivityAsUser(intent, opts,
- new UserHandle(UserHandle.USER_CURRENT));
+ new UserHandle(ad.userId));
} catch (SecurityException e) {
Log.e(TAG, "Recents does not have the permission to launch " + intent, e);
} catch (ActivityNotFoundException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java
index 2e0ee3606956..5ad965f427a0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java
@@ -16,6 +16,7 @@
package com.android.systemui.recent;
+import android.os.UserHandle;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
@@ -27,6 +28,7 @@ public final class TaskDescription {
final Intent intent; // launch intent for application
final String packageName; // used to override animations (see onClick())
final CharSequence description;
+ final int userId;
private Drawable mThumbnail; // generated by Activity.onCreateThumbnail()
private Drawable mIcon; // application package icon
@@ -35,7 +37,7 @@ public final class TaskDescription {
public TaskDescription(int _taskId, int _persistentTaskId,
ResolveInfo _resolveInfo, Intent _intent,
- String _packageName, CharSequence _description) {
+ String _packageName, CharSequence _description, int _userId) {
resolveInfo = _resolveInfo;
intent = _intent;
taskId = _taskId;
@@ -43,6 +45,7 @@ public final class TaskDescription {
description = _description;
packageName = _packageName;
+ userId = _userId;
}
public TaskDescription() {
@@ -53,6 +56,7 @@ public final class TaskDescription {
description = null;
packageName = null;
+ userId = UserHandle.USER_NULL;
}
public void setLoaded(boolean loaded) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
new file mode 100644
index 000000000000..b085211de5c2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
@@ -0,0 +1,67 @@
+package com.android.systemui.recents;
+
+import android.animation.TimeInterpolator;
+
+/**
+ * A pre-baked bezier-curved interpolator for quantum-paper transitions.
+ */
+public class BakedBezierInterpolator implements TimeInterpolator {
+ public static final BakedBezierInterpolator INSTANCE = new BakedBezierInterpolator();
+
+ /**
+ * Use the INSTANCE variable instead of instantiating.
+ */
+ private BakedBezierInterpolator() {
+ super();
+ }
+
+ /**
+ * Lookup table values.
+ * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+ * P0 (0,0)
+ * P1 (0.4, 0)
+ * P2 (0.2, 1.0)
+ * P3 (1.0, 1.0)
+ *
+ * Values sampled with x at regular intervals between 0 and 1.
+ *
+ * These values were generated using:
+ * ./scripts/bezier_interpolator_values_gen.py 0.4 0.2
+ */
+ private static final float[] VALUES = new float[] {
+ 0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f,
+ 0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f,
+ 0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f,
+ 0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f,
+ 0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f,
+ 0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f,
+ 0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f,
+ 0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f,
+ 0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f,
+ 0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f
+ };
+
+ private static final float STEP_SIZE = 1.0f / (VALUES.length - 1);
+
+ @Override
+ public float getInterpolation(float input) {
+ if (input >= 1.0f) {
+ return 1.0f;
+ }
+
+ if (input <= 0f) {
+ return 0f;
+ }
+
+ int position = Math.min(
+ (int)(input * (VALUES.length - 1)),
+ VALUES.length - 2);
+
+ float quantized = position * STEP_SIZE;
+ float difference = input - quantized;
+ float weight = difference / STEP_SIZE;
+
+ return VALUES[position] + weight * (VALUES[position + 1] - VALUES[position]);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 8c5c8fa15f84..86f188e288e1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -34,7 +34,7 @@ public class Constants {
// For debugging, this enables us to create mock recents tasks
public static final boolean EnableSystemServicesProxy = false;
// For debugging, this defines the number of mock recents packages to create
- public static final int SystemServicesProxyMockPackageCount = 12;
+ public static final int SystemServicesProxyMockPackageCount = 3;
// For debugging, this defines the number of mock recents tasks to create
public static final int SystemServicesProxyMockTaskCount = 75;
@@ -82,16 +82,8 @@ public class Constants {
}
public static class TaskStackView {
- public static class Animation {
- public static final int TaskRemovedReshuffleDuration = 200;
- public static final int SnapScrollBackDuration = 650;
- public static final int FilteredCurrentViewsDuration = 150;
- public static final int FilteredNewViewsDuration = 200;
- public static final int UnfilteredCurrentViewsDuration = 150;
- public static final int UnfilteredNewViewsDuration = 200;
- }
-
public static final int TaskStackOverscrollRange = 150;
+ public static final int FilterStartDelay = 25;
// The padding will be applied to the smallest dimension, and then applied to all sides
public static final float StackPaddingPct = 0.15f;
@@ -106,12 +98,6 @@ public class Constants {
}
public static class TaskView {
- public static class Animation {
- public static final int TaskDataUpdatedFadeDuration = 250;
- public static final int TaskIconOnEnterDuration = 175;
- public static final int TaskIconOnLeavingDuration = 75;
- }
-
public static final boolean AnimateFrontTaskIconOnEnterRecents = true;
public static final boolean AnimateFrontTaskIconOnLeavingRecents = true;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 3d47cb6dcfd8..4a0de0bae118 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -17,11 +17,11 @@
package com.android.systemui.recents;
import android.content.Context;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.TypedValue;
+import com.android.systemui.R;
/** A static Recents configuration for the current context
@@ -34,6 +34,11 @@ public class RecentsConfiguration {
public Rect systemInsets = new Rect();
public Rect displayRect = new Rect();
+ public float animationPxMovementPerSecond;
+
+ public int filteringCurrentViewsMinAnimDuration;
+ public int filteringNewViewsMinAnimDuration;
+
/** Private constructor */
private RecentsConfiguration() {}
@@ -58,6 +63,12 @@ public class RecentsConfiguration {
mDisplayMetrics = dm;
displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
+ animationPxMovementPerSecond =
+ res.getDimensionPixelSize(R.dimen.recents_animation_movement_in_dps_per_second);
+ filteringCurrentViewsMinAnimDuration =
+ res.getInteger(R.integer.recents_filter_animate_current_views_min_duration);
+ filteringNewViewsMinAnimDuration =
+ res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
}
public void updateSystemInsets(Rect insets) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index e193a95420f8..d661f287c13c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -414,7 +414,7 @@ public class RecentsTaskLoader {
// Create a new task
Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, activityLabel,
- activityIcon);
+ activityIcon, t.userId);
// Preload the specified number of apps
if (i >= (taskCount - preloadCount)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index f147fbc6f265..efcd948d830d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -51,9 +51,9 @@ public class SystemServicesProxy {
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
// Create a dummy icon
- mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
+ mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(mDummyIcon);
- c.drawColor(0xFFFF0000);
+ c.drawColor(0xFF999999);
c.setBitmap(null);
}
}
@@ -77,7 +77,7 @@ public class SystemServicesProxy {
rti.id = rti.persistentId = i;
rti.baseIntent = new Intent();
rti.baseIntent.setComponent(cn);
- rti.description = rti.activityLabel =
+ rti.description = rti.activityLabel = "" + i + " - " +
Long.toString(Math.abs(new Random().nextLong()), 36);
if (i % 2 == 0) {
rti.activityIcon = Bitmap.createBitmap(mDummyIcon);
@@ -118,7 +118,7 @@ public class SystemServicesProxy {
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
Bitmap thumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(thumbnail);
- c.drawColor(0xFF00ff00);
+ c.drawColor(0xff333333);
c.setBitmap(null);
return thumbnail;
}
@@ -178,7 +178,7 @@ public class SystemServicesProxy {
// If we are mocking, then return a mock label
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
- return new ColorDrawable(0xFFff0000);
+ return new ColorDrawable(0xFF666666);
}
return info.loadIcon(mPm);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 9048cba930a7..4a1b3b2749b5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -20,6 +20,19 @@ import android.graphics.Rect;
/* Common code */
public class Utilities {
+ /**
+ * Calculates a consistent animation duration (ms) for all animations depending on the movement
+ * of the object being animated.
+ */
+ public static int calculateTranslationAnimationDuration(int distancePx) {
+ return calculateTranslationAnimationDuration(distancePx, 100);
+ }
+ public static int calculateTranslationAnimationDuration(int distancePx, int minDuration) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ return Math.max(minDuration, (int) (1000f /* ms/s */ *
+ (Math.abs(distancePx) / config.animationPxMovementPerSecond)));
+ }
+
/** Scales a rect about its centroid */
public static void scaleRectAboutCenter(Rect r, float scale) {
if (scale != 1.0f) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index ed2ab2a5b91f..a0ff3b7dda8c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -65,15 +65,17 @@ public class Task {
public Bitmap activityIcon;
public Bitmap thumbnail;
public boolean isActive;
+ public int userId;
TaskCallbacks mCb;
public Task(int id, boolean isActive, Intent intent, String activityTitle,
- Bitmap activityIcon) {
+ Bitmap activityIcon, int userId) {
this.key = new TaskKey(id, intent);
this.activityLabel = activityTitle;
this.activityIcon = activityIcon;
this.isActive = isActive;
+ this.userId = userId;
}
/** Set the callbacks */
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 cb5279490ff0..1ebe2317883e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -257,9 +257,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
try {
if (opts != null) {
getContext().startActivityAsUser(i, opts.toBundle(),
- UserHandle.CURRENT);
+ new UserHandle(task.userId));
} else {
- getContext().startActivityAsUser(i, UserHandle.CURRENT);
+ getContext().startActivityAsUser(i, new UserHandle(task.userId));
}
} catch (ActivityNotFoundException anfe) {
Console.logError(getContext(), "Could not start Activity");
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 dfd608cb4342..fa06764e9b3e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -35,11 +35,11 @@ import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.OverScroller;
import com.android.systemui.R;
+import com.android.systemui.recents.BakedBezierInterpolator;
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsTaskLoader;
-import com.android.systemui.recents.SystemServicesProxy;
import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
@@ -76,6 +76,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
OverScroller mScroller;
ObjectAnimator mScrollAnimator;
+ // Filtering
+ AnimatorSet mFilterChildrenAnimator;
+
// Optimizations
int mHwLayersRefCount;
int mStackViewsAnimationDuration;
@@ -180,7 +183,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
*/
private ArrayList<TaskViewTransform> getStackTransforms(ArrayList<Task> tasks,
int stackScroll,
- int[] visibleRangeOut) {
+ int[] visibleRangeOut,
+ boolean boundTranslationsToRect) {
// XXX: Optimization: Use binary search to find the visible range
ArrayList<TaskViewTransform> taskTransforms = new ArrayList<TaskViewTransform>();
@@ -196,6 +200,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
lastVisibleIndex = i;
}
+
+ if (boundTranslationsToRect) {
+ transform.translationY = Math.min(transform.translationY, mRect.bottom);
+ }
}
if (visibleRangeOut != null) {
visibleRangeOut[0] = firstVisibleIndex;
@@ -219,7 +227,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int stackScroll = getStackScroll();
ArrayList<Task> tasks = mStack.getTasks();
ArrayList<TaskViewTransform> taskTransforms = getStackTransforms(tasks, stackScroll,
- visibleRange);
+ visibleRange, false);
// Update the visible state of all the tasks
int taskCount = tasks.size();
@@ -286,7 +294,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/** Animates the stack scroll into bounds */
- ObjectAnimator animateBoundScroll(int duration) {
+ ObjectAnimator animateBoundScroll() {
int curScroll = getStackScroll();
int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
if (newScroll != curScroll) {
@@ -298,16 +306,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
abortBoundScrollAnimation();
// Start a new scroll animation
- animateScroll(curScroll, newScroll, duration);
+ animateScroll(curScroll, newScroll);
mScrollAnimator.start();
}
return mScrollAnimator;
}
/** Animates the stack scroll */
- void animateScroll(int curScroll, int newScroll, int duration) {
+ void animateScroll(int curScroll, int newScroll) {
mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
- mScrollAnimator.setDuration(duration);
+ mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
+ curScroll, 250));
+ mScrollAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
@@ -625,7 +635,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
updateMinMaxScroll(true);
- requestSynchronizeStackViewsWithModel(Constants.Values.TaskStackView.Animation.TaskRemovedReshuffleDuration);
+ int movement = (int) (Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height());
+ requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
}
@Override
@@ -635,20 +646,22 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// (filtered) stack
// XXX: Use HW Layers
- // Stash the scroll for us to restore to when we unfilter
+ // Stash the scroll and filtered task for us to restore to when we unfilter
mStashedScroll = getStackScroll();
// Compute the transforms of the items in the current stack
final ArrayList<TaskViewTransform> curTaskTransforms =
- getStackTransforms(curStack, mStashedScroll, null);
+ getStackTransforms(curStack, mStashedScroll, null, true);
- // Bound the new stack scroll
+ // Scroll the item to the top of the stack (sans-peek) rect so that we can see it better
updateMinMaxScroll(false);
+ float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
+ setStackScrollRaw((int) (newStack.indexOfTask(filteredTask) * overlapHeight));
boundScrollRaw();
- // Compute the transforms of the items in the new stack
+ // Compute the transforms of the items in the new stack after setting the new scroll
final ArrayList<TaskViewTransform> taskTransforms =
- getStackTransforms(mStack.getTasks(), getStackScroll(), null);
+ getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
// Animate all of the existing views on screen either out of view (if they are not visible
// in the new stack) or to their final positions in the new stack
@@ -656,13 +669,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
final ArrayList<Task> tasks = mStack.getTasks();
ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
int childCount = getChildCount();
+ int movement = 0;
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
TaskViewTransform toTransform;
int taskIndex = tasks.indexOf(task);
- if ((taskIndex < 0) || !taskTransforms.get(taskIndex).visible) {
- // Compose a new transform that animates the task view out of view
+
+ boolean willBeInvisible = (taskIndex < 0) || !taskTransforms.get(taskIndex).visible;
+ if (willBeInvisible) {
+ // Compose a new transform that fades and slides the task out of view
TaskViewTransform fromTransform = curTaskTransforms.get(curStack.indexOf(task));
toTransform = new TaskViewTransform(fromTransform);
tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
@@ -671,23 +687,49 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
childrenToReturnToPool.add(tv);
} else {
toTransform = taskTransforms.get(taskIndex);
+
+ // Use the movement of the visible views to calculate the duration of the animation
+ movement = Math.max(movement,
+ Math.abs(toTransform.translationY - (int) tv.getTranslationY()));
}
childViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
}
- AnimatorSet childViewAnimSet = new AnimatorSet();
- childViewAnimSet.setDuration(
- Constants.Values.TaskStackView.Animation.FilteredCurrentViewsDuration);
- childViewAnimSet.addListener(new AnimatorListenerAdapter() {
+ // Cancel the previous animation
+ if (mFilterChildrenAnimator != null) {
+ mFilterChildrenAnimator.cancel();
+ mFilterChildrenAnimator.removeAllListeners();
+ }
+
+ // Create a new animation for the existing children
+ final RecentsConfiguration config = RecentsConfiguration.getInstance();
+ mFilterChildrenAnimator = new AnimatorSet();
+ mFilterChildrenAnimator.setDuration(
+ Utilities.calculateTranslationAnimationDuration(movement,
+ config.filteringCurrentViewsMinAnimDuration));
+ mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+ mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
+ boolean isCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ isCancelled = true;
+ }
+
@Override
public void onAnimationEnd(Animator animation) {
+ if (isCancelled) return;
+
// Return all the removed children to the view pool
for (TaskView tv : childrenToReturnToPool) {
mViewPool.returnViewToPool(tv);
}
// For views that are not already visible, animate them in
+ ArrayList<Animator> newViewsAnims = new ArrayList<Animator>();
int taskCount = tasks.size();
+ int movement = 0;
+ int offset = 0;
for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i);
TaskViewTransform toTransform = taskTransforms.get(i);
@@ -697,20 +739,38 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView tv = getChildViewForTask(task);
if (tv == null) {
tv = mViewPool.pickUpViewFromPool(task, task);
+ // Compose a new transform that fades and slides the new task in
+ fromTransform = new TaskViewTransform(toTransform);
+ tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
+ tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
- // Animate from the current position to the new position
- tv.prepareTaskTransformForFilterTaskVisible(fromTransform);
- tv.updateViewPropertiesToTaskTransform(fromTransform,
- toTransform,
- Constants.Values.TaskStackView.Animation.FilteredNewViewsDuration);
+ Animator anim = tv.getAnimatorToTaskTransform(toTransform);
+ anim.setStartDelay(offset *
+ Constants.Values.TaskStackView.FilterStartDelay);
+ newViewsAnims.add(anim);
+
+ // Use the movement of the newly visible views to calculate the duration
+ // of the animation
+ movement = Math.max(movement, Math.abs(toTransform.translationY -
+ fromTransform.translationY));
+ offset++;
}
}
+
+ // Animate the new views in
+ mFilterChildrenAnimator = new AnimatorSet();
+ mFilterChildrenAnimator.setDuration(
+ Utilities.calculateTranslationAnimationDuration(movement,
+ config.filteringNewViewsMinAnimDuration));
+ mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+ mFilterChildrenAnimator.playTogether(newViewsAnims);
+ mFilterChildrenAnimator.start();
}
invalidate();
}
});
- childViewAnimSet.playTogether(childViewAnims);
- childViewAnimSet.start();
+ mFilterChildrenAnimator.playTogether(childViewAnims);
+ mFilterChildrenAnimator.start();
}
@Override
@@ -718,16 +778,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Compute the transforms of the items in the current stack
final int curScroll = getStackScroll();
final ArrayList<TaskViewTransform> curTaskTransforms =
- getStackTransforms(curStack, curScroll, null);
+ getStackTransforms(curStack, curScroll, null, true);
// Restore the stashed scroll
updateMinMaxScroll(false);
setStackScrollRaw(mStashedScroll);
boundScrollRaw();
- // Compute the transforms of the items in the new stack
+ // Compute the transforms of the items in the new stack after restoring the stashed scroll
final ArrayList<TaskViewTransform> taskTransforms =
- getStackTransforms(mStack.getTasks(), getStackScroll(), null);
+ getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
// Animate all of the existing views out of view (if they are not in the visible range in
// the new stack) or to their final positions in the new stack
@@ -735,29 +795,55 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
final ArrayList<Task> tasks = mStack.getTasks();
ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
int childCount = getChildCount();
+ int movement = 0;
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
int taskIndex = tasks.indexOf(task);
- TaskViewTransform transform;
+ TaskViewTransform toTransform;
// If the view is no longer visible, then we should just animate it out
- if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
- transform = new TaskViewTransform(curTaskTransforms.get(curStack.indexOf(task)));
- tv.prepareTaskTransformForFilterTaskVisible(transform);
+ boolean willBeInvisible = taskIndex < 0 || !taskTransforms.get(taskIndex).visible;
+ if (willBeInvisible) {
+ toTransform = new TaskViewTransform(taskTransforms.get(taskIndex));
+ tv.prepareTaskTransformForFilterTaskVisible(toTransform);
childrenToRemove.add(tv);
} else {
- transform = taskTransforms.get(taskIndex);
+ toTransform = taskTransforms.get(taskIndex);
+ // Use the movement of the visible views to calculate the duration of the animation
+ movement = Math.max(movement, Math.abs(toTransform.translationY -
+ (int) tv.getTranslationY()));
}
- childViewAnims.add(tv.getAnimatorToTaskTransform(transform));
+
+ Animator anim = tv.getAnimatorToTaskTransform(toTransform);
+ childViewAnims.add(anim);
+ }
+
+ // Cancel the previous animation
+ if (mFilterChildrenAnimator != null) {
+ mFilterChildrenAnimator.cancel();
+ mFilterChildrenAnimator.removeAllListeners();
}
- AnimatorSet childViewAnimSet = new AnimatorSet();
- childViewAnimSet.setDuration(
- Constants.Values.TaskStackView.Animation.UnfilteredCurrentViewsDuration);
- childViewAnimSet.addListener(new AnimatorListenerAdapter() {
+ // Create a new animation for the existing children
+ final RecentsConfiguration config = RecentsConfiguration.getInstance();
+ mFilterChildrenAnimator = new AnimatorSet();
+ mFilterChildrenAnimator.setDuration(
+ Utilities.calculateTranslationAnimationDuration(movement,
+ config.filteringCurrentViewsMinAnimDuration));
+ mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+ mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
+ boolean isCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ isCancelled = true;
+ }
+
@Override
public void onAnimationEnd(Animator animation) {
+ if (isCancelled) return;
+
// Return all the removed children to the view pool
for (TaskView tv : childrenToRemove) {
mViewPool.returnViewToPool(tv);
@@ -768,8 +854,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// For views that are not already visible, animate them in
ArrayList<Animator> newViewAnims = new ArrayList<Animator>();
- AnimatorSet newViewAnimSet = new AnimatorSet();
int taskCount = tasks.size();
+ int movement = 0;
int offset = 0;
for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i);
@@ -780,34 +866,46 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// For views that are not already visible, animate them in
tv = mViewPool.pickUpViewFromPool(task, task);
- // Animate in this new view
+ // Compose a new transform to fade and slide the new task in
TaskViewTransform fromTransform = new TaskViewTransform(toTransform);
tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
- newViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
+
+ Animator anim = tv.getAnimatorToTaskTransform(toTransform);
+ anim.setStartDelay(offset *
+ Constants.Values.TaskStackView.FilterStartDelay);
+ newViewAnims.add(anim);
+ // Use the movement of the newly visible views to calculate the duration
+ // of the animation
+ movement = Math.max(movement,
+ Math.abs(toTransform.translationY - fromTransform.translationY));
offset++;
}
}
}
// Run the animation
- newViewAnimSet.setDuration(
- Constants.Values.TaskStackView.Animation.UnfilteredNewViewsDuration);
- newViewAnimSet.playTogether(newViewAnims);
- newViewAnimSet.addListener(new AnimatorListenerAdapter() {
+ mFilterChildrenAnimator = new AnimatorSet();
+ mFilterChildrenAnimator.setDuration(
+ Utilities.calculateTranslationAnimationDuration(movement,
+ config.filteringNewViewsMinAnimDuration));
+ mFilterChildrenAnimator.playTogether(newViewAnims);
+ mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Decrement the hw layers ref count
decHwLayersRefCount("unfilteredNewViews");
}
});
- newViewAnimSet.start();
-
+ mFilterChildrenAnimator.start();
invalidate();
}
});
- childViewAnimSet.playTogether(childViewAnims);
- childViewAnimSet.start();
+ mFilterChildrenAnimator.playTogether(childViewAnims);
+ mFilterChildrenAnimator.start();
+
+ // Clear the saved vars
+ mStashedScroll = 0;
}
/**** ViewPoolConsumer Implementation ****/
@@ -1056,7 +1154,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
// Animate the scroll back if we've cancelled
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+ mSv.animateBoundScroll();
// Disable HW layers
if (mIsScrolling) {
mSv.decHwLayersRefCount("stackScroll");
@@ -1186,7 +1284,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
} else if (mSv.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
// XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+ mSv.animateBoundScroll();
}
if (mIsScrolling) {
@@ -1220,7 +1318,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
if (mSv.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
// XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+ mSv.animateBoundScroll();
}
mActivePointerId = INACTIVE_POINTER_ID;
mIsScrolling = false;
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 2c27d440f33c..e99fecb022a8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -20,20 +20,24 @@ import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.recents.BakedBezierInterpolator;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
+import java.util.Random;
+
/* A task view */
public class TaskView extends FrameLayout implements View.OnClickListener, Task.TaskCallbacks {
@@ -131,7 +135,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
.scaleY(toTransform.scale)
.alpha(toTransform.alpha)
.setDuration(duration)
- .setInterpolator(new AccelerateDecelerateInterpolator())
+ .setInterpolator(BakedBezierInterpolator.INSTANCE)
.withLayer()
.start();
} else {
@@ -190,7 +194,8 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
.translationX(0)
.translationY(0)
.setStartDelay(235)
- .setDuration(Constants.Values.TaskView.Animation.TaskIconOnEnterDuration)
+ .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
.withLayer()
.start();
}
@@ -206,8 +211,8 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
.translationX(translate / 2)
.translationY(-translate)
.setStartDelay(0)
- .setDuration(Constants.Values.TaskView.Animation.TaskIconOnLeavingDuration)
- .setInterpolator(new DecelerateInterpolator())
+ .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
.withLayer()
.withEndAction(r)
.start();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index f34903696982..844b96480d87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -970,7 +970,11 @@ public abstract class BaseStatusBar extends SystemUI implements
if (mPanelSlightlyVisible != visible) {
mPanelSlightlyVisible = visible;
try {
- mBarService.onPanelRevealed();
+ if (visible) {
+ mBarService.onPanelRevealed();
+ } else {
+ mBarService.onPanelHidden();
+ }
} catch (RemoteException ex) {
// Won't fail unless the world has ended.
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index f1c8e0158fca..89da08f40834 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar;
import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -35,11 +37,14 @@ public class SignalClusterView
static final boolean DEBUG = false;
static final String TAG = "SignalClusterView";
+ static final PorterDuffColorFilter PROBLEM_FILTER
+ = new PorterDuffColorFilter(0xffab653b, PorterDuff.Mode.SRC_ATOP);
NetworkController mNC;
private boolean mWifiVisible = false;
private int mWifiStrengthId = 0;
+ private boolean mInetProblem;
private boolean mMobileVisible = false;
private int mMobileStrengthId = 0, mMobileTypeId = 0;
private boolean mIsAirplaneMode = false;
@@ -96,19 +101,22 @@ public class SignalClusterView
}
@Override
- public void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription) {
+ public void setWifiIndicators(boolean visible, int strengthIcon, boolean problem,
+ String contentDescription) {
mWifiVisible = visible;
mWifiStrengthId = strengthIcon;
+ mInetProblem = problem;
mWifiDescription = contentDescription;
apply();
}
@Override
- public void setMobileDataIndicators(boolean visible, int strengthIcon,
+ public void setMobileDataIndicators(boolean visible, int strengthIcon, boolean problem,
int typeIcon, String contentDescription, String typeContentDescription) {
mMobileVisible = visible;
mMobileStrengthId = strengthIcon;
+ mInetProblem = problem;
mMobileTypeId = typeIcon;
mMobileDescription = contentDescription;
mMobileTypeDescription = typeContentDescription;
@@ -158,13 +166,17 @@ public class SignalClusterView
apply();
}
+ private void applyInetProblem(ImageView iv) {
+ iv.setColorFilter(mInetProblem ? PROBLEM_FILTER : null);
+ }
+
// Run after each indicator change.
private void apply() {
if (mWifiGroup == null) return;
if (mWifiVisible) {
mWifi.setImageResource(mWifiStrengthId);
-
+ applyInetProblem(mWifi);
mWifiGroup.setContentDescription(mWifiDescription);
mWifiGroup.setVisibility(View.VISIBLE);
} else {
@@ -179,7 +191,7 @@ public class SignalClusterView
if (mMobileVisible && !mIsAirplaneMode) {
mMobile.setImageResource(mMobileStrengthId);
mMobileType.setImageResource(mMobileTypeId);
-
+ applyInetProblem(mMobile);
mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription);
mMobileGroup.setVisibility(View.VISIBLE);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 3c8af3007b00..20fb225c8382 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -529,7 +529,6 @@ public class PanelView extends FrameLayout {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
- mTracking = true;
if (mHandleView != null) {
mHandleView.setPressed(true);
// catch the press state change
@@ -561,6 +560,7 @@ public class PanelView extends FrameLayout {
if (h < -mTouchSlop) {
mInitialOffsetOnTouch = mExpandedHeight;
mInitialTouchY = y;
+ mTracking = true;
return true;
}
}
@@ -793,7 +793,7 @@ public class PanelView extends FrameLayout {
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%f closing=%s"
+ pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s"
+ " tracking=%s rubberbanding=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
+ "]",
this.getClass().getSimpleName(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 09f1695aa30a..92c008ebbbd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -126,6 +126,7 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
private String mConnectedNetworkTypeName;
private int mInetCondition = 0;
+ private int mLastInetCondition = 0;
private static final int INET_CONDITION_THRESHOLD = 50;
private boolean mAirplaneMode = false;
@@ -156,9 +157,9 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
boolean mDataAndWifiStacked = false;
public interface SignalCluster {
- void setWifiIndicators(boolean visible, int strengthIcon,
+ void setWifiIndicators(boolean visible, int strengthIcon, boolean problem,
String contentDescription);
- void setMobileDataIndicators(boolean visible, int strengthIcon,
+ void setMobileDataIndicators(boolean visible, int strengthIcon, boolean problem,
int typeIcon, String contentDescription, String typeContentDescription);
void setIsAirplaneMode(boolean is, int airplaneIcon);
}
@@ -288,6 +289,7 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
// only show wifi in the cluster if connected or if wifi-only
mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature),
mWifiIconId,
+ mInetCondition == 0,
mContentDescriptionWifi);
if (mIsWimaxEnabled && mWimaxConnected) {
@@ -295,6 +297,7 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
cluster.setMobileDataIndicators(
true,
mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId,
+ mInetCondition == 0,
mDataTypeIconId,
mContentDescriptionWimax,
mContentDescriptionDataType);
@@ -303,6 +306,7 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
cluster.setMobileDataIndicators(
mHasMobileDataFeature,
mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId,
+ mInetCondition == 0,
mDataTypeIconId,
mContentDescriptionPhoneSignal,
mContentDescriptionDataType);
@@ -1145,6 +1149,7 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
if (mLastPhoneSignalIconId != mPhoneSignalIconId
|| mLastWifiIconId != mWifiIconId
+ || mLastInetCondition != mInetCondition
|| mLastWimaxIconId != mWimaxIconId
|| mLastDataTypeIconId != mDataTypeIconId
|| mLastAirplaneMode != mAirplaneMode
@@ -1179,6 +1184,10 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
mLastWifiIconId = mWifiIconId;
}
+ if (mLastInetCondition != mInetCondition) {
+ mLastInetCondition = mInetCondition;
+ }
+
// the wimax icon on phones
if (mLastWimaxIconId != mWimaxIconId) {
mLastWimaxIconId = mWimaxIconId;
@@ -1424,6 +1433,7 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
cluster.setWifiIndicators(
show,
iconId,
+ mDemoInetCondition == 0,
"Demo");
}
}
@@ -1456,6 +1466,7 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
cluster.setMobileDataIndicators(
show,
iconId,
+ mDemoInetCondition == 0,
mDemoDataTypeIconId,
"Demo",
"Demo");
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 6e025bb1541d..c6972b118d6f 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -268,7 +268,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
if (Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
mItems.add(
- new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
+ new SinglePressAction(com.android.internal.R.drawable.ic_lock_bugreport,
R.string.global_action_bug_report) {
public void onPress() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index f1db904c6c26..79ed8667af99 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -25,6 +25,8 @@ import static android.view.WindowManager.LayoutParams.*;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.ActivityOptions;
+import android.os.Looper;
+import android.transition.Fade;
import android.transition.Scene;
import android.transition.Transition;
import android.transition.TransitionInflater;
@@ -109,7 +111,6 @@ import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
import java.util.Map;
/**
@@ -253,8 +254,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private ActivityOptions mActivityOptions;
private SceneTransitionListener mSceneTransitionListener;
- private boolean mTriggerEarly = true;
+ private boolean mAllowEnterOverlap = true;
+ private boolean mAllowExitOverlap = true;
private Map<String, String> mSharedElementsMap;
+ private ArrayList<View> mTransitioningViews;
static class WindowManagerHolder {
static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
@@ -4081,14 +4084,26 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
- public void setTransitionOptions(ActivityOptions options, SceneTransitionListener listener) {
+ public void setTransitionOptions(Bundle options, SceneTransitionListener listener) {
mSceneTransitionListener = listener;
- mActivityOptions = options;
+ ActivityOptions activityOptions = null;
+ if (options != null) {
+ activityOptions = new ActivityOptions(options);
+ if (activityOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) {
+ activityOptions = null;
+ }
+ }
+ mActivityOptions = activityOptions;
+ }
+
+ @Override
+ public void setAllowOverlappingEnterTransition(boolean allow) {
+ mAllowEnterOverlap = allow;
}
@Override
- public void setTriggerEarlyEnterTransition(boolean triggerEarly) {
- mTriggerEarly = triggerEarly;
+ public void setAllowOverlappingExitTransition(boolean allow) {
+ mAllowExitOverlap = allow;
}
@Override
@@ -4097,7 +4112,50 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
- public Bundle startExitTransition(ActivityOptions activityOptions) {
+ public void restoreViewVisibilityAfterTransitionToCallee() {
+ if (mTransitioningViews != null) {
+ setViewVisibility(mTransitioningViews, View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void startExitTransitionToCaller(final Runnable onTransitionEnd) {
+ Transition transition;
+ if (mContentScene == null || mTransitionManager == null || mActivityOptions == null
+ || (transition = mTransitionManager.getEnterTransition(mContentScene)) == null) {
+ onTransitionEnd.run();
+ return;
+ }
+ if (mAllowExitOverlap) {
+ TransitionSet transitionSet = new TransitionSet();
+ transitionSet.addTransition(transition);
+ Fade fade = new Fade();
+ transitionSet.addTransition(fade);
+ transition = transitionSet;
+ }
+
+ final ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
+ mapSharedElements(sharedElements);
+ final Bundle sharedElementArgs = new Bundle();
+ captureTerminalSharedElementState(sharedElements, sharedElementArgs);
+
+ final ArrayList<View> transitioningViews = new ArrayList<View>();
+ mDecor.captureTransitioningViews(transitioningViews);
+ transitioningViews.removeAll(sharedElements.values());
+
+ mSceneTransitionListener.convertToTranslucent();
+ transition = transition.clone();
+ Rect epicenter = calcEpicenter(sharedElements, mActivityOptions.getSharedElementNames());
+ transition.setEpicenterCallback(new FixedEpicenterCallback(epicenter));
+ ExitSceneBack exitScene =
+ new ExitSceneBack(onTransitionEnd, sharedElementArgs, sharedElements.values());
+ exitScene.start(transition);
+ mTransitionManager.beginDelayedTransition(mDecor, transition);
+ setViewVisibility(transitioningViews, View.INVISIBLE);
+ }
+
+ @Override
+ public Bundle startExitTransitionToCallee(Bundle options) {
if (mContentScene == null) {
return null;
}
@@ -4106,16 +4164,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return null;
}
+ ActivityOptions activityOptions = new ActivityOptions(options);
ArrayMap<String, View> sharedElements = findSharedElements(activityOptions);
// Find exiting Views and shared elements
- final ArrayList<View> transitioningViews = new ArrayList<View>();
- mDecor.captureTransitioningViews(transitioningViews);
- transitioningViews.removeAll(sharedElements.values());
+ ArrayList<View> transitioningViews = captureTransitioningViews(sharedElements.values());
- Transition exitTransition = cloneAndSetTransitionTargets(transition,
+ Transition exitTransition = addTransitionTargets(transition,
transitioningViews, true);
- Transition sharedElementTransition = cloneAndSetTransitionTargets(transition,
+ Transition sharedElementTransition = addTransitionTargets(transition,
transitioningViews, false);
// transitionSet is the total exit transition, including hero animation.
@@ -4123,8 +4180,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
transitionSet.addTransition(exitTransition);
transitionSet.addTransition(sharedElementTransition);
+ Rect epicenter = calcEpicenter(sharedElements, activityOptions.getSharedElementNames());
+ FixedEpicenterCallback epicenterCallback = new FixedEpicenterCallback(epicenter);
+ transitionSet.setEpicenterCallback(epicenterCallback);
+
updateExitActivityOptions(activityOptions, sharedElements,
- sharedElementTransition, exitTransition);
+ sharedElementTransition, transitioningViews, exitTransition, epicenterCallback);
// Start exiting the Views that need to exit
TransitionManager.beginDelayedTransition(mDecor, transitionSet);
@@ -4133,6 +4194,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return activityOptions.toBundle();
}
+ private ArrayList<View> captureTransitioningViews(Collection<View> sharedElements) {
+ mTransitioningViews = new ArrayList<View>();
+ mDecor.captureTransitioningViews(mTransitioningViews);
+ ArrayList<View> transitioningViews = (ArrayList<View>) mTransitioningViews.clone();
+ transitioningViews.removeAll(sharedElements);
+ return transitioningViews;
+ }
+
private ArrayMap<String, View> findSharedElements(ActivityOptions activityOptions) {
ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
mDecor.findSharedElements(sharedElements);
@@ -4149,9 +4218,18 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return sharedElements;
}
+ private static void runOnUiThread(Handler handler, Runnable runnable) {
+ if (handler.getLooper() != Looper.myLooper()) {
+ handler.post(runnable);
+ } else {
+ runnable.run();
+ }
+ }
+
private void updateExitActivityOptions(ActivityOptions activityOptions,
final Map<String, View> sharedElements, Transition sharedElementTransition,
- Transition exitTransition) {
+ final ArrayList<View> transitioningViews, Transition exitTransition,
+ final Transition.EpicenterCallback epicenterCallback) {
// Schedule capturing of the shared element state
final Bundle sharedElementArgs = new Bundle();
@@ -4159,30 +4237,88 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
ActivityOptions.SharedElementSource sharedElementSource
= new ActivityOptions.SharedElementSource() {
+ private Handler mHandler = new Handler();
+
@Override
public Bundle getSharedElementExitState() {
return sharedElementArgs;
}
@Override
- public void acceptedSharedElements(ArrayList<String> sharedElementNames) {
+ public void acceptedSharedElements(final ArrayList<String> sharedElementNames) {
if (sharedElementNames.size() == sharedElements.size()) {
return; // They were all accepted
}
- Transition transition = mTransitionManager.getExitTransition(mContentScene).clone();
- TransitionManager.beginDelayedTransition(mDecor, transition);
- for (String name: sharedElements.keySet()) {
- if (!sharedElementNames.contains(name)) {
- sharedElements.get(name).setVisibility(View.INVISIBLE);
+ runOnUiThread(mHandler, new Runnable() {
+ @Override
+ public void run() {
+ Transition transition = mTransitionManager.getExitTransition(mContentScene);
+ transition = transition.clone();
+ transition.setEpicenterCallback(epicenterCallback);
+ TransitionManager.beginDelayedTransition(mDecor, transition);
+ for (String name : sharedElements.keySet()) {
+ if (!sharedElementNames.contains(name)) {
+ sharedElements.get(name).setVisibility(View.INVISIBLE);
+ }
+ }
+ sharedElements.keySet().retainAll(sharedElementNames);
}
- }
- sharedElements.keySet().retainAll(sharedElementNames);
+ });
}
@Override
public void hideSharedElements() {
if (sharedElements != null) {
- setViewVisibility(sharedElements.values(), View.INVISIBLE);
+ runOnUiThread(mHandler, new Runnable() {
+ @Override
+ public void run() {
+ setViewVisibility(sharedElements.values(), View.INVISIBLE);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void restore(final Bundle sharedElementState) {
+ runOnUiThread(mHandler, new Runnable() {
+ @Override
+ public void run() {
+ mTransitioningViews = null;
+ Transition transition = mTransitionManager.getExitTransition(mContentScene);
+ transition = transition.clone();
+ transition.setEpicenterCallback(epicenterCallback);
+ setSharedElementState(sharedElements, sharedElementState);
+ setViewVisibility(sharedElements.values(), View.VISIBLE);
+ if (mSceneTransitionListener != null) {
+ mSceneTransitionListener.sharedElementStart(transition);
+ mDecor.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
+ mSceneTransitionListener.sharedElementEnd();
+ return true;
+ }
+ });
+ }
+ TransitionManager.beginDelayedTransition(mDecor, transition);
+ setViewVisibility(transitioningViews, View.VISIBLE);
+ for (View sharedElement: sharedElements.values()) {
+ sharedElement.requestLayout();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void prepareForRestore() {
+ if (mTransitioningViews != null) {
+ runOnUiThread(mHandler, new Runnable() {
+ @Override
+ public void run() {
+ setViewVisibility(mTransitioningViews, View.INVISIBLE);
+ }
+ });
}
}
};
@@ -4207,22 +4343,18 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
});
}
- private static Transition cloneAndSetTransitionTargets(Transition transition,
- List<View> views, boolean add) {
- transition = transition.clone();
- if (!transition.getTargetIds().isEmpty() || !transition.getTargets().isEmpty()) {
- TransitionSet set = new TransitionSet();
- set.addTransition(transition);
- transition = set;
- }
+ private static Transition addTransitionTargets(Transition transition, Collection<View> views,
+ boolean add) {
+ TransitionSet set = new TransitionSet();
+ set.addTransition(transition.clone());
for (View view: views) {
if (add) {
- transition.addTarget(view);
+ set.addTarget(view);
} else {
- transition.excludeTarget(view, true);
+ set.excludeTarget(view, true);
}
}
- return transition;
+ return set;
}
private static void setViewVisibility(Collection<View> views, int visibility) {
@@ -4231,6 +4363,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
+ private static void setSharedElementState(Map<String, View> sharedElements,
+ Bundle sharedElementState) {
+ int[] tempLoc = new int[2];
+ for (Map.Entry<String, View> entry: sharedElements.entrySet()) {
+ setSharedElementState(entry.getValue(), entry.getKey(), sharedElementState, tempLoc);
+ }
+ }
+
/**
* Sets the captured values from a previous
* {@link #captureSharedElementState(android.view.View, String, android.os.Bundle, int[])}
@@ -4247,23 +4387,27 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return;
}
- int x = sharedElementBundle.getInt(KEY_SCREEN_X);
- view.getLocationOnScreen(tempLoc);
- int offsetX = x - tempLoc[0];
- view.offsetLeftAndRight(offsetX);
+ float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
+ view.setTranslationZ(z);
+ int x = sharedElementBundle.getInt(KEY_SCREEN_X);
+ int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
int width = sharedElementBundle.getInt(KEY_WIDTH);
- view.setRight(view.getLeft() + width);
+ int height = sharedElementBundle.getInt(KEY_HEIGHT);
- int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
- int offsetY = y - tempLoc[1];
- view.offsetTopAndBottom(offsetY);
+ int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
+ int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
+ view.measure(widthSpec, heightSpec);
- int height = sharedElementBundle.getInt(KEY_HEIGHT);
- view.setBottom(view.getTop() + height);
+ ViewGroup parent = (ViewGroup) view.getParent();
+ parent.getLocationOnScreen(tempLoc);
+ int left = x - tempLoc[0];
+ int top = y - tempLoc[1];
+ int right = left + width;
+ int bottom = top + height;
+ view.layout(left, top, right, bottom);
- float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
- view.setTranslationZ(z);
+ view.requestLayout();
}
/**
@@ -4297,6 +4441,124 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
transitionArgs.putBundle(name, sharedElementBundle);
}
+ private void mapSharedElements(ArrayMap<String, View> sharedElements) {
+ ArrayList<String> sharedElementNames = mActivityOptions.getSharedElementNames();
+ if (sharedElementNames != null) {
+ mDecor.findSharedElements(sharedElements);
+ if (mSharedElementsMap != null) {
+ for (Map.Entry<String, String> entry : mSharedElementsMap.entrySet()) {
+ View sharedElement = sharedElements.remove(entry.getValue());
+ if (sharedElement != null) {
+ sharedElements.put(entry.getKey(), sharedElement);
+ }
+ }
+ }
+ sharedElements.keySet().retainAll(sharedElementNames);
+ }
+ }
+
+ private static Rect calcEpicenter(ArrayMap<String, View> sharedElements,
+ ArrayList<String> sharedElementNames) {
+ if (sharedElementNames != null) {
+ for (String name: sharedElementNames) {
+ if (name.startsWith("android:")) {
+ return null;
+ }
+ View view = sharedElements.get(name);
+ if (view != null) {
+ int[] loc = new int[2];
+ view.getLocationOnScreen(loc);
+ int left = loc[0] + Math.round(view.getTranslationX());
+ int top = loc[1] + Math.round(view.getTranslationY());
+ int right = left + view.getWidth();
+ int bottom = top + view.getHeight();
+ return new Rect(left, top, right, bottom);
+ }
+ }
+ }
+ return null;
+ }
+
+ private class ExitSceneBack extends Transition.TransitionListenerAdapter implements
+ Animator.AnimatorListener {
+ private boolean mExitTransitionComplete;
+ private boolean mBackgroundFadeComplete;
+ private boolean mOnCompleteExecuted;
+ private boolean mSharedElementTransitioned;
+ private Runnable mOnComplete;
+ private Bundle mSharedElementArgs;
+ private Collection<View> mSharedElements;
+
+ public ExitSceneBack(Runnable onComplete, Bundle sharedElementArgs,
+ Collection<View> sharedElements) {
+ mOnComplete = onComplete;
+ mSharedElementArgs = sharedElementArgs;
+ mSharedElements = sharedElements;
+ }
+
+ public void start(Transition exitTransition) {
+ if (mActivityOptions != null) {
+ mActivityOptions.dispatchPrepareRestore();
+ }
+ exitTransition.addListener(this);
+ Drawable background = mDecor.getBackground();
+ if (background != null) {
+ ObjectAnimator animator = ObjectAnimator.ofInt(background, "alpha", 0);
+ animator.addListener(this);
+ animator.start();
+ } else {
+ mBackgroundFadeComplete = true;
+ startCalledActivityEnter();
+ }
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ transition.removeListener(this);
+ mExitTransitionComplete = true;
+ notifyComplete();
+ if (!mAllowExitOverlap) {
+ startCalledActivityEnter();
+ }
+ }
+
+ private void notifyComplete() {
+ if (mExitTransitionComplete && mBackgroundFadeComplete
+ && mSharedElementTransitioned && !mOnCompleteExecuted) {
+ mOnComplete.run();
+ mSceneTransitionListener.nullPendingTransition();
+ mOnCompleteExecuted = true;
+ }
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mBackgroundFadeComplete = true;
+ if (mAllowExitOverlap) {
+ startCalledActivityEnter();
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ private void startCalledActivityEnter() {
+ mActivityOptions.dispatchRestore(mSharedElementArgs);
+ setViewVisibility(mSharedElements, View.INVISIBLE);
+ mSharedElementTransitioned = true;
+ notifyComplete();
+ }
+ }
+
/**
* Provides code for handling the Activity transition entering scene.
* When the first scene is laid out (onPreDraw), it makes views invisible.
@@ -4317,6 +4579,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private boolean mEnterTransitionStarted;
private ArrayMap<String, View> mSharedElementTargets = new ArrayMap<String, View>();
private ArrayList<View> mEnteringViews = new ArrayList<View>();
+ private Transition.EpicenterCallback mEpicenterCallback;
public EnterScene() {
mSceneTransitionListener.nullPendingTransition();
@@ -4335,33 +4598,25 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (!mEnterTransitionStarted && mSceneTransitionListener != null) {
mEnterTransitionStarted = true;
mDecor.captureTransitioningViews(mEnteringViews);
- ArrayList<String> sharedElementNames = mActivityOptions.getSharedElementNames();
- if (sharedElementNames != null) {
- mDecor.findSharedElements(mSharedElementTargets);
- if (mSharedElementsMap != null) {
- for (Map.Entry<String, String> entry : mSharedElementsMap.entrySet()) {
- View sharedElement = mSharedElementTargets.remove(entry.getValue());
- if (sharedElement != null) {
- mSharedElementTargets.put(entry.getKey(), sharedElement);
- }
- }
- }
- mSharedElementTargets.keySet().retainAll(sharedElementNames);
- mEnteringViews.removeAll(mSharedElementTargets.values());
- }
+ mapSharedElements(mSharedElementTargets);
+ mEnteringViews.removeAll(mSharedElementTargets.values());
+ Rect epicenter = calcEpicenter(mSharedElementTargets,
+ mActivityOptions.getSharedElementNames());
+ mEpicenterCallback = new FixedEpicenterCallback(epicenter);
setViewVisibility(mEnteringViews, View.INVISIBLE);
setViewVisibility(mSharedElementTargets.values(), View.INVISIBLE);
- if (mTriggerEarly) {
+ if (mAllowEnterOverlap) {
beginEnterScene();
}
observer.addOnPreDrawListener(this);
+ return false;
} else {
mHandler.postDelayed(this, MAX_TRANSITION_START_WAIT);
mActivityOptions.dispatchSceneTransitionStarted(this,
new ArrayList<String>(mSharedElementTargets.keySet()));
+ return !mSharedElementReadyReceived;
}
- return true;
}
public void start() {
@@ -4375,43 +4630,48 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
- public void sharedElementTransitionComplete(Bundle transitionArgs) {
+ public void sharedElementTransitionComplete(final Bundle transitionArgs) {
if (!mSharedElementReadyReceived) {
mSharedElementReadyReceived = true;
mHandler.removeCallbacks(this);
mHandler.postDelayed(this, MAX_TRANSITION_FINISH_WAIT);
if (!mSharedElementTargets.isEmpty()) {
- Transition transition = getTransitionManager().getEnterTransition(
- mContentScene);
- if (transition == null) {
- transition = TransitionManager.getDefaultTransition();
- }
- transition = transition.clone();
- if (transitionArgs == null) {
- TransitionManager.beginDelayedTransition(mDecor, transition);
- setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
- } else {
- int[] tempLoc = new int[2];
- for (Map.Entry<String, View> entry: mSharedElementTargets.entrySet()) {
- setSharedElementState(entry.getValue(), entry.getKey(), transitionArgs,
- tempLoc);
+ runOnUiThread(mHandler, new Runnable() {
+ @Override
+ public void run() {
+ Transition transition = getTransitionManager().getEnterTransition(
+ mContentScene);
+ if (transition == null) {
+ transition = TransitionManager.getDefaultTransition();
+ }
+ transition = addTransitionTargets(transition,
+ mSharedElementTargets.values(),
+ true);
+ transition.setEpicenterCallback(mEpicenterCallback);
+ if (transitionArgs == null) {
+ TransitionManager.beginDelayedTransition(mDecor, transition);
+ setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
+ } else {
+ mSceneTransitionListener.sharedElementStart(transition);
+ setSharedElementState(mSharedElementTargets, transitionArgs);
+ setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
+ mDecor.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mDecor.getViewTreeObserver()
+ .removeOnPreDrawListener(this);
+ mSceneTransitionListener.sharedElementEnd();
+ mActivityOptions.dispatchSharedElementsReady();
+ return true;
+ }
+ });
+ TransitionManager.beginDelayedTransition(mDecor, transition);
+ }
}
- setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
- mSceneTransitionListener.sharedElementStart(transition);
- mDecor.getViewTreeObserver().addOnPreDrawListener(
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
- mSceneTransitionListener.sharedElementEnd();
- mActivityOptions.dispatchSharedElementsReady();
- return true;
- }
- });
- TransitionManager.beginDelayedTransition(mDecor, transition);
- }
+ });
}
- if (mTriggerEarly) {
+ if (mAllowEnterOverlap) {
fadeInBackground();
}
}
@@ -4436,9 +4696,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mAllDone = true;
sharedElementTransitionComplete(null);
mHandler.removeCallbacks(this);
- if (!mTriggerEarly) {
- beginEnterScene();
- fadeInBackground();
+ if (!mAllowEnterOverlap) {
+ runOnUiThread(mHandler, new Runnable() {
+ @Override
+ public void run() {
+ beginEnterScene();
+ fadeInBackground();
+ }
+ });
}
}
@@ -4462,10 +4727,25 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private void beginEnterScene() {
Transition transition = getTransitionManager().getEnterTransition(mContentScene);
if (transition == null) {
- transition = TransitionManager.getDefaultTransition().clone();
+ transition = TransitionManager.getDefaultTransition();
}
+ transition = addTransitionTargets(transition, mEnteringViews, true);
+ transition.setEpicenterCallback(mEpicenterCallback);
TransitionManager.beginDelayedTransition(mDecor, transition);
setViewVisibility(mEnteringViews, View.VISIBLE);
}
}
+
+ private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
+ private Rect mEpicenter;
+
+ public FixedEpicenterCallback(Rect epicenter) {
+ mEpicenter = epicenter;
+ }
+
+ @Override
+ public Rect getEpicenter(Transition transition) {
+ return mEpicenter;
+ }
+ };
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 57c2f929bb20..0b688b6fbf9f 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -4690,7 +4690,11 @@ public class BackupManagerService extends IBackupManager.Stub {
// ----- Restore handling -----
- private boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
+ static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
+ if (target == null) {
+ return false;
+ }
+
// If the target resides on the system partition, we allow it to restore
// data from the like-named package in a restore set even if the signatures
// do not match. (Unlike general applications, those flashed to the system
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index 495da886fa65..39f2441f3b55 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -19,15 +19,19 @@ package com.android.server.backup;
import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
+import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.util.Slog;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -42,6 +46,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.Objects;
+
/**
* We back up the signatures of each package so that during a system restore,
* we can verify that the app whose data we think we have matches the app
@@ -58,6 +64,9 @@ public class PackageManagerBackupAgent extends BackupAgent {
// is stored using the package name as a key)
private static final String GLOBAL_METADATA_KEY = "@meta@";
+ // key under which we store the identity of the user's chosen default home app
+ private static final String DEFAULT_HOME_KEY = "@home@";
+
private List<PackageInfo> mAllPackages;
private PackageManager mPackageManager;
// version & signature info of each app in a restore set
@@ -68,7 +77,15 @@ public class PackageManagerBackupAgent extends BackupAgent {
private final HashSet<String> mExisting = new HashSet<String>();
private int mStoredSdkVersion;
private String mStoredIncrementalVersion;
+ private ComponentName mStoredHomeComponent;
+ private long mStoredHomeVersion;
+ private Signature[] mStoredHomeSigs;
+
private boolean mHasMetadata;
+ private ComponentName mRestoredHome;
+ private long mRestoredHomeVersion;
+ private String mRestoredHomeInstaller;
+ private Signature[] mRestoredHomeSignatures;
public class Metadata {
public int versionCode;
@@ -136,7 +153,50 @@ public class PackageManagerBackupAgent extends BackupAgent {
mExisting.clear();
}
+ long homeVersion = 0;
+ Signature[] homeSigs = null;
+ PackageInfo homeInfo = null;
+ String homeInstaller = null;
+ ComponentName home = getPreferredHomeComponent();
+ if (home != null) {
+ try {
+ homeInfo = mPackageManager.getPackageInfo(home.getPackageName(),
+ PackageManager.GET_SIGNATURES);
+ homeInstaller = mPackageManager.getInstallerPackageName(home.getPackageName());
+ homeVersion = homeInfo.versionCode;
+ homeSigs = homeInfo.signatures;
+ } catch (NameNotFoundException e) {
+ Slog.w(TAG, "Can't access preferred home info");
+ // proceed as though there were no preferred home set
+ home = null;
+ }
+ }
+
try {
+ // We need to push a new preferred-home-app record if:
+ // 1. the version of the home app has changed since our last backup;
+ // 2. the home app [or absence] we now use differs from the prior state,
+ // OR 3. it looks like we use the same home app + version as before, but
+ // the signatures don't match so we treat them as different apps.
+ final boolean needHomeBackup = (homeVersion != mStoredHomeVersion)
+ || Objects.equals(home, mStoredHomeComponent)
+ || (home != null
+ && !BackupManagerService.signaturesMatch(mStoredHomeSigs, homeInfo));
+ if (needHomeBackup) {
+ if (DEBUG) {
+ Slog.i(TAG, "Home preference changed; backing up new state " + home);
+ }
+ if (home != null) {
+ outputBufferStream.writeUTF(home.flattenToString());
+ outputBufferStream.writeLong(homeVersion);
+ outputBufferStream.writeUTF(homeInstaller);
+ writeSignatureArray(outputBufferStream, homeSigs);
+ writeEntity(data, DEFAULT_HOME_KEY, outputBuffer.toByteArray());
+ } else {
+ data.writeEntityHeader(DEFAULT_HOME_KEY, -1);
+ }
+ }
+
/*
* Global metadata:
*
@@ -146,6 +206,7 @@ public class PackageManagerBackupAgent extends BackupAgent {
* String incremental -- the incremental release name of the OS stored in
* the backup set.
*/
+ outputBuffer.reset();
if (!mExisting.contains(GLOBAL_METADATA_KEY)) {
if (DEBUG) Slog.v(TAG, "Storing global metadata key");
outputBufferStream.writeInt(Build.VERSION.SDK_INT);
@@ -238,7 +299,7 @@ public class PackageManagerBackupAgent extends BackupAgent {
}
// Finally, write the new state blob -- just the list of all apps we handled
- writeStateFile(mAllPackages, newState);
+ writeStateFile(mAllPackages, home, homeVersion, homeSigs, newState);
}
private static void writeEntity(BackupDataOutput data, String key, byte[] bytes)
@@ -286,6 +347,19 @@ public class PackageManagerBackupAgent extends BackupAgent {
+ " (" + mStoredIncrementalVersion + " vs "
+ Build.VERSION.INCREMENTAL + ")");
}
+ } else if (key.equals(DEFAULT_HOME_KEY)) {
+ String cn = inputBufferStream.readUTF();
+ mRestoredHome = ComponentName.unflattenFromString(cn);
+ mRestoredHomeVersion = inputBufferStream.readLong();
+ mRestoredHomeInstaller = inputBufferStream.readUTF();
+ mRestoredHomeSignatures = readSignatureArray(inputBufferStream);
+ if (DEBUG) {
+ Slog.i(TAG, " read preferred home app " + mRestoredHome
+ + " version=" + mRestoredHomeVersion
+ + " installer=" + mRestoredHomeVersion
+ + " sig=" + mRestoredHomeVersion);
+ }
+
} else {
// it's a file metadata record
int versionCode = inputBufferStream.readInt();
@@ -365,18 +439,34 @@ public class PackageManagerBackupAgent extends BackupAgent {
mStateVersions.clear();
mStoredSdkVersion = 0;
mStoredIncrementalVersion = null;
+ mStoredHomeComponent = null;
+ mStoredHomeVersion = 0;
+ mStoredHomeSigs = null;
// The state file is just the list of app names we have stored signatures for
// with the exception of the metadata block, to which is also appended the
// version numbers corresponding with the last time we wrote this PM block.
// If they mismatch the current system, we'll re-store the metadata key.
FileInputStream instream = new FileInputStream(stateFile.getFileDescriptor());
- DataInputStream in = new DataInputStream(instream);
+ BufferedInputStream inbuffer = new BufferedInputStream(instream);
+ DataInputStream in = new DataInputStream(inbuffer);
- int bufSize = 256;
- byte[] buf = new byte[bufSize];
try {
String pkg = in.readUTF();
+
+ // First comes the preferred home app data, if any, headed by the DEFAULT_HOME_KEY tag
+ if (pkg.equals(DEFAULT_HOME_KEY)) {
+ // flattened component name, version, signature of the home app
+ mStoredHomeComponent = ComponentName.unflattenFromString(in.readUTF());
+ mStoredHomeVersion = in.readLong();
+ mStoredHomeSigs = readSignatureArray(in);
+
+ pkg = in.readUTF(); // set up for the next block of state
+ } else {
+ // else no preferred home app on the ancestral device - fall through to the rest
+ }
+
+ // After (possible) home app data comes the global metadata block
if (pkg.equals(GLOBAL_METADATA_KEY)) {
mStoredSdkVersion = in.readInt();
mStoredIncrementalVersion = in.readUTF();
@@ -386,7 +476,7 @@ public class PackageManagerBackupAgent extends BackupAgent {
return;
}
- // The global metadata was first; now read all the apps
+ // The global metadata was last; now read all the apps
while (true) {
pkg = in.readUTF();
int versionCode = in.readInt();
@@ -401,13 +491,28 @@ public class PackageManagerBackupAgent extends BackupAgent {
}
}
+ private ComponentName getPreferredHomeComponent() {
+ return mPackageManager.getHomeActivities(new ArrayList<ResolveInfo>());
+ }
+
// Util: write out our new backup state file
- private void writeStateFile(List<PackageInfo> pkgs, ParcelFileDescriptor stateFile) {
+ private void writeStateFile(List<PackageInfo> pkgs, ComponentName preferredHome,
+ long homeVersion, Signature[] homeSignatures, ParcelFileDescriptor stateFile) {
FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor());
- DataOutputStream out = new DataOutputStream(outstream);
+ BufferedOutputStream outbuf = new BufferedOutputStream(outstream);
+ DataOutputStream out = new DataOutputStream(outbuf);
+ // by the time we get here we know we've done all our backing up
try {
- // by the time we get here we know we've stored the global metadata record
+ // If we remembered a preferred home app, record that
+ if (preferredHome != null) {
+ out.writeUTF(DEFAULT_HOME_KEY);
+ out.writeUTF(preferredHome.flattenToString());
+ out.writeLong(homeVersion);
+ writeSignatureArray(out, homeSignatures);
+ }
+
+ // Conclude with the metadata block
out.writeUTF(GLOBAL_METADATA_KEY);
out.writeInt(Build.VERSION.SDK_INT);
out.writeUTF(Build.VERSION.INCREMENTAL);
@@ -417,9 +522,10 @@ public class PackageManagerBackupAgent extends BackupAgent {
out.writeUTF(pkg.packageName);
out.writeInt(pkg.versionCode);
}
+
+ out.flush();
} catch (IOException e) {
Slog.e(TAG, "Unable to write package manager state file!");
- return;
}
}
}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 0f78c9bd7eaf..976893475b60 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -58,7 +58,11 @@ option java_package com.android.server
2751 notification_cancel (uid|1|5),(pid|1|5),(pkg|3),(id|1|5),(tag|3),(userid|1|5),(required_flags|1),(forbidden_flags|1),(reason|1|5),(listener|3)
# when someone tries to cancel all of the notifications for a particular package
2752 notification_cancel_all (uid|1|5),(pid|1|5),(pkg|3),(userid|1|5),(required_flags|1),(forbidden_flags|1),(reason|1|5),(listener|3)
-
+# when the notification panel is shown
+# Note: New tag range starts here since 2753+ have been used below.
+27500 notification_panel_revealed
+# when the notification panel is hidden
+27501 notification_panel_hidden
# ---------------------------
# Watchdog.java
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 94f699fccd65..f59edc7f83e3 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -71,6 +71,7 @@ final class UiModeManagerService extends SystemService {
private boolean mCarModeKeepsScreenOn;
private boolean mDeskModeKeepsScreenOn;
private boolean mTelevision;
+ private boolean mWatch;
private boolean mComputedNightMode;
int mCurUiMode = 0;
@@ -176,6 +177,7 @@ final class UiModeManagerService extends SystemService {
PackageManager.FEATURE_TELEVISION) ||
context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
+ mWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
mNightMode = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
@@ -339,8 +341,12 @@ final class UiModeManagerService extends SystemService {
}
private void updateConfigurationLocked() {
- int uiMode = mTelevision ? Configuration.UI_MODE_TYPE_TELEVISION : mDefaultUiModeType;
- if (mCarModeEnabled) {
+ int uiMode = mDefaultUiModeType;
+ if (mTelevision) {
+ uiMode = Configuration.UI_MODE_TYPE_TELEVISION;
+ } else if (mWatch) {
+ uiMode = Configuration.UI_MODE_TYPE_WATCH;
+ } else if (mCarModeEnabled) {
uiMode = Configuration.UI_MODE_TYPE_CAR;
} else if (isDeskDockState(mDockState)) {
uiMode = Configuration.UI_MODE_TYPE_DESK;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 33b12c571671..d596472b5eb5 100644..100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -522,13 +522,6 @@ final class ActivityRecord {
if (fullscreen == toOpaque) {
return false;
}
- AttributeCache.Entry ent =
- AttributeCache.instance().get(packageName, realTheme, styleable.Window, userId);
- if (ent == null
- || !ent.array.getBoolean(styleable.Window_windowIsTranslucent, false)
- || ent.array.getBoolean(styleable.Window_windowIsFloating, false)) {
- return false;
- }
// Keep track of the number of fullscreen activities in this task.
task.numFullscreen += toOpaque ? +1 : -1;
@@ -956,8 +949,8 @@ final class ActivityRecord {
// for another app to start, then we have paused dispatching
// for this activity.
ActivityRecord r = this;
- final ActivityStack stack = task.stack;
if (r.waitingVisible) {
+ final ActivityStack stack = mStackSupervisor.getFocusedStack();
// Hmmm, who might we be waiting for?
r = stack.mResumedActivity;
if (r == null) {
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 4c8dcc363689..e0591a284f09 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -29,5 +29,6 @@ public interface NotificationDelegate {
String pkg, String tag, int id,
int uid, int initialPid, String message, int userId);
void onPanelRevealed();
+ void onPanelHidden();
boolean allowDisable(int what, IBinder token, String pkg);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3b6d2886df7f..8be2410fbeee 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -966,6 +966,7 @@ public class NotificationManagerService extends SystemService {
@Override
public void onPanelRevealed() {
+ EventLogTags.writeNotificationPanelRevealed();
synchronized (mNotificationList) {
// sound
mSoundNotification = null;
@@ -998,6 +999,11 @@ public class NotificationManagerService extends SystemService {
}
@Override
+ public void onPanelHidden() {
+ EventLogTags.writeNotificationPanelHidden();
+ }
+
+ @Override
public void onNotificationError(int callingUid, int callingPid, String pkg, String tag, int id,
int uid, int initialPid, String message, int userId) {
Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
@@ -1915,8 +1921,8 @@ public class NotificationManagerService extends SystemService {
mNotificationList.add(r);
mUsageStats.registerPostedByApp(r);
} else {
- old = mNotificationList.remove(index);
- mNotificationList.add(index, r);
+ old = mNotificationList.get(index);
+ mNotificationList.set(index, r);
mUsageStats.registerUpdatedByApp(r);
// Make sure we don't lose the foreground service state.
if (old != null) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 80c3c8e6483d..b85a50608f68 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -406,6 +406,7 @@ public final class PowerManagerService extends com.android.server.SystemService
private static native void nativeReleaseSuspendBlocker(String name);
private static native void nativeSetInteractive(boolean enable);
private static native void nativeSetAutoSuspend(boolean enable);
+ private static native void nativeSendPowerHint(int hintId, int data);
public PowerManagerService(Context context) {
super(context);
@@ -2548,6 +2549,12 @@ public final class PowerManagerService extends com.android.server.SystemService
}
@Override // Binder call
+ public void powerHint(int hintId, int data) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+ nativeSendPowerHint(hintId, data);
+ }
+
+ @Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) {
if (lock == null) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 4ce02c1d07c7..e4b5f3ae0d41 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -535,6 +535,17 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
@Override
+ public void onPanelHidden() throws RemoteException {
+ enforceStatusBarService();
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mNotificationDelegate.onPanelHidden();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void onNotificationClick(String pkg, String tag, int id, int userId) {
enforceStatusBarService();
final int callingUid = Binder.getCallingUid();
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index e1069aecaeb4..b3247ff2f94f 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -150,7 +150,7 @@ static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t styl
status_t status = android_view_PointerIcon_loadSystemIcon(env,
contextObj, style, &pointerIcon);
if (!status) {
- pointerIcon.bitmap.copyTo(&outSpriteIcon->bitmap, SkBitmap::kARGB_8888_Config);
+ pointerIcon.bitmap.copyTo(&outSpriteIcon->bitmap, kNative_8888_SkColorType);
outSpriteIcon->hotSpotX = pointerIcon.hotSpotX;
outSpriteIcon->hotSpotY = pointerIcon.hotSpotY;
}
@@ -1297,7 +1297,7 @@ static void nativeVibrate(JNIEnv* env,
size_t patternSize = env->GetArrayLength(patternObj);
if (patternSize > MAX_VIBRATE_PATTERN_SIZE) {
- ALOGI("Skipped requested vibration because the pattern size is %d "
+ ALOGI("Skipped requested vibration because the pattern size is %zu "
"which is more than the maximum supported size of %d.",
patternSize, MAX_VIBRATE_PATTERN_SIZE);
return; // limit to reasonable size
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 151e134ee3ba..dbf5439a9aff 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -189,6 +189,18 @@ static void nativeSetAutoSuspend(JNIEnv *env, jclass clazz, jboolean enable) {
}
}
+static void nativeSendPowerHint(JNIEnv *env, jclass clazz, jint hintId, jint data) {
+ int data_param = data;
+
+ if (gPowerModule && gPowerModule->powerHint) {
+ if(data)
+ gPowerModule->powerHint(gPowerModule, (power_hint_t)hintId, &data_param);
+ else {
+ gPowerModule->powerHint(gPowerModule, (power_hint_t)hintId, NULL);
+ }
+ }
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gPowerManagerServiceMethods[] = {
@@ -205,6 +217,8 @@ static JNINativeMethod gPowerManagerServiceMethods[] = {
(void*) nativeSetInteractive },
{ "nativeSetAutoSuspend", "(Z)V",
(void*) nativeSetAutoSuspend },
+ { "nativeSendPowerHint", "(II)V",
+ (void*) nativeSendPowerHint },
};
#define FIND_CLASS(var, className) \
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 38bfa00d7564..e0dab785bc47 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1342,6 +1342,11 @@ bool AaptGroupEntry::getUiModeTypeName(const char* name,
(out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
| ResTable_config::UI_MODE_TYPE_APPLIANCE;
return true;
+ } else if (strcmp(name, "watch") == 0) {
+ if (out) out->uiMode =
+ (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+ | ResTable_config::UI_MODE_TYPE_WATCH;
+ return true;
}
return false;
diff --git a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java
new file mode 100644
index 000000000000..914a359e3171
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate used to provide implementation of a select few native methods of {@link AssetManager}
+ * <p/>
+ * Through the layoutlib_create tool, the original native methods of AssetManager have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class AssetManager_Delegate {
+
+ @LayoutlibDelegate
+ /*package*/ static long newTheme(AssetManager manager) {
+ return Resources_Theme_Delegate.getDelegateManager()
+ .addNewDelegate(new Resources_Theme_Delegate());
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void deleteTheme(AssetManager manager, long theme) {
+ Resources_Theme_Delegate.getDelegateManager().removeJavaReferenceFor(theme);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void applyThemeStyle(long theme, int styleRes, boolean force) {
+ Resources_Theme_Delegate.getDelegateManager().getDelegate(theme).force = force;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
index c9d615c6ec6f..31d1594edc0a 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
@@ -16,7 +16,13 @@
package android.content.res;
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.ResourceReference;
+import com.android.ide.common.rendering.api.StyleResourceValue;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.RenderSessionImpl;
+import com.android.resources.ResourceType;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.content.res.Resources.NotFoundException;
@@ -25,7 +31,7 @@ import android.util.AttributeSet;
import android.util.TypedValue;
/**
- * Delegate used to provide new implementation of a select few methods of {@link Resources$Theme}
+ * Delegate used to provide new implementation of a select few methods of {@link Resources.Theme}
*
* Through the layoutlib_create tool, the original methods of Theme have been replaced
* by calls to methods of the same name in this delegate class.
@@ -33,11 +39,28 @@ import android.util.TypedValue;
*/
public class Resources_Theme_Delegate {
+ // Whether to use the Theme.mThemeResId as primary theme.
+ boolean force;
+
+ // ---- delegate manager ----
+
+ private static final DelegateManager<Resources_Theme_Delegate> sManager =
+ new DelegateManager<Resources_Theme_Delegate>(Resources_Theme_Delegate.class);
+
+ public static DelegateManager<Resources_Theme_Delegate> getDelegateManager() {
+ return sManager;
+ }
+
+ // ---- delegate methods. ----
+
@LayoutlibDelegate
/*package*/ static TypedArray obtainStyledAttributes(
Resources thisResources, Theme thisTheme,
int[] attrs) {
- return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
+ boolean changed = setupResources(thisTheme);
+ TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
+ restoreResources(changed);
+ return ta;
}
@LayoutlibDelegate
@@ -45,15 +68,21 @@ public class Resources_Theme_Delegate {
Resources thisResources, Theme thisTheme,
int resid, int[] attrs)
throws NotFoundException {
- return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs);
+ boolean changed = setupResources(thisTheme);
+ TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs);
+ restoreResources(changed);
+ return ta;
}
@LayoutlibDelegate
/*package*/ static TypedArray obtainStyledAttributes(
Resources thisResources, Theme thisTheme,
AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
- return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(
- set, attrs, defStyleAttr, defStyleRes);
+ boolean changed = setupResources(thisTheme);
+ TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set, attrs,
+ defStyleAttr, defStyleRes);
+ restoreResources(changed);
+ return ta;
}
@LayoutlibDelegate
@@ -61,7 +90,45 @@ public class Resources_Theme_Delegate {
Resources thisResources, Theme thisTheme,
int resid, TypedValue outValue,
boolean resolveRefs) {
- return RenderSessionImpl.getCurrentContext().resolveThemeAttribute(
+ boolean changed = setupResources(thisTheme);
+ boolean found = RenderSessionImpl.getCurrentContext().resolveThemeAttribute(
resid, outValue, resolveRefs);
+ restoreResources(changed);
+ return found;
+ }
+
+ // ---- private helper methods ----
+
+ private static boolean setupResources(Theme thisTheme) {
+ Resources_Theme_Delegate themeDelegate = sManager.getDelegate(thisTheme.getNativeTheme());
+ StyleResourceValue style = resolveStyle(thisTheme.getAppliedStyleResId());
+ if (style != null) {
+ RenderSessionImpl.getCurrentContext().getRenderResources()
+ .applyStyle(style, themeDelegate.force);
+ return true;
+ }
+ return false;
+ }
+
+ private static void restoreResources(boolean changed) {
+ if (changed) {
+ RenderSessionImpl.getCurrentContext().getRenderResources().clearStyles();
+ }
+ }
+
+ @Nullable
+ private static StyleResourceValue resolveStyle(int nativeResid) {
+ if (nativeResid == 0) {
+ return null;
+ }
+ BridgeContext context = RenderSessionImpl.getCurrentContext();
+ ResourceReference theme = context.resolveId(nativeResid);
+ if (theme.isFramework()) {
+ return (StyleResourceValue) context.getRenderResources()
+ .getFrameworkResource(ResourceType.STYLE, theme.getName());
+ } else {
+ return (StyleResourceValue) context.getRenderResources()
+ .getProjectResource(ResourceType.STYLE, theme.getName());
+ }
}
}
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 b9294ab3c0f9..9ee2f60add7e 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
@@ -16,6 +16,7 @@
package com.android.layoutlib.bridge.android;
+import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
@@ -109,7 +110,7 @@ public final class BridgeContext extends Context {
// maps for dynamically generated id representing style objects (StyleResourceValue)
private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap;
private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap;
- private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style
+ private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
// cache for TypedArray generated from IStyleResourceValue object
private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
@@ -315,6 +316,11 @@ public final class BridgeContext extends Context {
}
}
+ // The base value for R.style is 0x01030000 and the custom style is 0x02030000.
+ // So, if the second byte is 03, it's probably a style.
+ if ((id >> 16 & 0xFF) == 0x03) {
+ return getStyleByDynamicId(id);
+ }
return null;
}
@@ -455,7 +461,10 @@ public final class BridgeContext extends Context {
@Override
public final TypedArray obtainStyledAttributes(int[] attrs) {
- return createStyleBasedTypedArray(mRenderResources.getCurrentTheme(), attrs);
+ // No style is specified here, so create the typed array based on the default theme
+ // and the styles already applied to it. A null value of style indicates that the default
+ // theme should be used.
+ return createStyleBasedTypedArray(null, attrs);
}
@Override
@@ -723,11 +732,13 @@ public final class BridgeContext extends Context {
/**
* Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
- * values found in the given style.
+ * values found in the given style. If no style is specified, the default theme, along with the
+ * styles applied to it are used.
+ *
* @see #obtainStyledAttributes(int, int[])
*/
- private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs)
- throws Resources.NotFoundException {
+ private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style,
+ int[] attrs) throws Resources.NotFoundException {
List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
@@ -740,8 +751,14 @@ public final class BridgeContext extends Context {
if (attribute != null) {
// look for the value in the given style
- ResourceValue resValue = mRenderResources.findItemInStyle(style,
- attribute.getFirst(), attribute.getSecond());
+ ResourceValue resValue;
+ if (style != null) {
+ resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(),
+ attribute.getSecond());
+ } else {
+ resValue = mRenderResources.findItemInTheme(attribute.getFirst(),
+ attribute.getSecond());
+ }
if (resValue != null) {
// resolve it to make sure there are no references left.
@@ -756,7 +773,6 @@ public final class BridgeContext extends Context {
return ta;
}
-
/**
* The input int[] attrs is a list of attributes. The returns a list of information about
* each attributes. The information is (name, isFramework)
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 3414b3e13db8..b9f2ed9689ff 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -51,6 +51,11 @@ public class BridgePowerManager implements IPowerManager {
}
@Override
+ public void powerHint(int hintId, int data) {
+ // pass for now.
+ }
+
+ @Override
public void crash(String arg0) throws RemoteException {
// pass for now.
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 42360388f53b..e0c05de6299f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -126,6 +126,9 @@ public final class CreateInfo implements ICreateInfo {
"android.content.res.Resources$Theme#obtainStyledAttributes",
"android.content.res.Resources$Theme#resolveAttribute",
"android.content.res.Resources#localeToLanguageTag",
+ "android.content.res.AssetManager#newTheme",
+ "android.content.res.AssetManager#deleteTheme",
+ "android.content.res.AssetManager#applyThemeStyle",
"android.content.res.TypedArray#getValueAt",
"android.graphics.BitmapFactory#finishDecode",
"android.os.Handler#sendMessageAtTime",