Merge "ListViews in ScrollViews and ScrollViews in ListViews"
diff --git a/api/current.txt b/api/current.txt
index b7c5380..06d1ab0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1858,28 +1858,28 @@
field public static final int TextAppearance_Medium = 16973892; // 0x1030044
field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045
field public static final int TextAppearance_Quantum = 16974352; // 0x1030210
- field public static final int TextAppearance_Quantum_Body1 = 16974546; // 0x10302d2
- field public static final int TextAppearance_Quantum_Body2 = 16974545; // 0x10302d1
- field public static final int TextAppearance_Quantum_Button = 16974549; // 0x10302d5
- field public static final int TextAppearance_Quantum_Caption = 16974547; // 0x10302d3
+ field public static final int TextAppearance_Quantum_Body1 = 16974542; // 0x10302ce
+ field public static final int TextAppearance_Quantum_Body2 = 16974541; // 0x10302cd
+ field public static final int TextAppearance_Quantum_Button = 16974545; // 0x10302d1
+ field public static final int TextAppearance_Quantum_Caption = 16974543; // 0x10302cf
field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974353; // 0x1030211
- field public static final int TextAppearance_Quantum_Display1 = 16974541; // 0x10302cd
- field public static final int TextAppearance_Quantum_Display2 = 16974540; // 0x10302cc
- field public static final int TextAppearance_Quantum_Display3 = 16974539; // 0x10302cb
- field public static final int TextAppearance_Quantum_Display4 = 16974538; // 0x10302ca
- field public static final int TextAppearance_Quantum_Headline = 16974542; // 0x10302ce
+ field public static final int TextAppearance_Quantum_Display1 = 16974537; // 0x10302c9
+ field public static final int TextAppearance_Quantum_Display2 = 16974536; // 0x10302c8
+ field public static final int TextAppearance_Quantum_Display3 = 16974535; // 0x10302c7
+ field public static final int TextAppearance_Quantum_Display4 = 16974534; // 0x10302c6
+ field public static final int TextAppearance_Quantum_Headline = 16974538; // 0x10302ca
field public static final int TextAppearance_Quantum_Inverse = 16974354; // 0x1030212
field public static final int TextAppearance_Quantum_Large = 16974355; // 0x1030213
field public static final int TextAppearance_Quantum_Large_Inverse = 16974356; // 0x1030214
field public static final int TextAppearance_Quantum_Medium = 16974357; // 0x1030215
field public static final int TextAppearance_Quantum_Medium_Inverse = 16974358; // 0x1030216
- field public static final int TextAppearance_Quantum_Menu = 16974548; // 0x10302d4
+ field public static final int TextAppearance_Quantum_Menu = 16974544; // 0x10302d0
field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974359; // 0x1030217
field public static final int TextAppearance_Quantum_SearchResult_Title = 16974360; // 0x1030218
field public static final int TextAppearance_Quantum_Small = 16974361; // 0x1030219
field public static final int TextAppearance_Quantum_Small_Inverse = 16974362; // 0x103021a
- field public static final int TextAppearance_Quantum_Subhead = 16974544; // 0x10302d0
- field public static final int TextAppearance_Quantum_Title = 16974543; // 0x10302cf
+ field public static final int TextAppearance_Quantum_Subhead = 16974540; // 0x10302cc
+ field public static final int TextAppearance_Quantum_Title = 16974539; // 0x10302cb
field public static final int TextAppearance_Quantum_Widget = 16974364; // 0x103021c
field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974365; // 0x103021d
field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974366; // 0x103021e
@@ -2329,118 +2329,114 @@
field public static final int Widget_Quantum_ActionMode = 16974423; // 0x1030257
field public static final int Widget_Quantum_AutoCompleteTextView = 16974424; // 0x1030258
field public static final int Widget_Quantum_Button = 16974425; // 0x1030259
- field public static final int Widget_Quantum_ButtonBar = 16974433; // 0x1030261
- field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974434; // 0x1030262
+ field public static final int Widget_Quantum_ButtonBar = 16974431; // 0x103025f
+ field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974432; // 0x1030260
field public static final int Widget_Quantum_Button_Borderless = 16974426; // 0x103025a
field public static final int Widget_Quantum_Button_Borderless_Small = 16974427; // 0x103025b
field public static final int Widget_Quantum_Button_Inset = 16974428; // 0x103025c
- field public static final int Widget_Quantum_Button_Paper = 16974431; // 0x103025f
- field public static final int Widget_Quantum_Button_Paper_Color = 16974432; // 0x1030260
field public static final int Widget_Quantum_Button_Small = 16974429; // 0x103025d
field public static final int Widget_Quantum_Button_Toggle = 16974430; // 0x103025e
- field public static final int Widget_Quantum_CalendarView = 16974435; // 0x1030263
- field public static final int Widget_Quantum_CheckedTextView = 16974436; // 0x1030264
- field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974437; // 0x1030265
- field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974438; // 0x1030266
- field public static final int Widget_Quantum_CompoundButton_Star = 16974439; // 0x1030267
- field public static final int Widget_Quantum_DatePicker = 16974440; // 0x1030268
- field public static final int Widget_Quantum_DropDownItem = 16974441; // 0x1030269
- field public static final int Widget_Quantum_DropDownItem_Spinner = 16974442; // 0x103026a
- field public static final int Widget_Quantum_EditText = 16974443; // 0x103026b
- field public static final int Widget_Quantum_ExpandableListView = 16974444; // 0x103026c
- field public static final int Widget_Quantum_FastScroll = 16974445; // 0x103026d
- field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974446; // 0x103026e
- field public static final int Widget_Quantum_GridView = 16974447; // 0x103026f
- field public static final int Widget_Quantum_HorizontalScrollView = 16974448; // 0x1030270
- field public static final int Widget_Quantum_ImageButton = 16974449; // 0x1030271
- field public static final int Widget_Quantum_Light = 16974475; // 0x103028b
- field public static final int Widget_Quantum_Light_ActionBar = 16974476; // 0x103028c
- field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974477; // 0x103028d
- field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974478; // 0x103028e
- field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974479; // 0x103028f
- field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974480; // 0x1030290
- field public static final int Widget_Quantum_Light_ActionButton = 16974481; // 0x1030291
- field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974482; // 0x1030292
- field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974483; // 0x1030293
- field public static final int Widget_Quantum_Light_ActionMode = 16974484; // 0x1030294
- field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974485; // 0x1030295
- field public static final int Widget_Quantum_Light_Button = 16974486; // 0x1030296
- field public static final int Widget_Quantum_Light_ButtonBar = 16974494; // 0x103029e
- field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974495; // 0x103029f
- field public static final int Widget_Quantum_Light_Button_Borderless = 16974487; // 0x1030297
- field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974488; // 0x1030298
- field public static final int Widget_Quantum_Light_Button_Inset = 16974489; // 0x1030299
- field public static final int Widget_Quantum_Light_Button_Paper = 16974492; // 0x103029c
- field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974493; // 0x103029d
- field public static final int Widget_Quantum_Light_Button_Small = 16974490; // 0x103029a
- field public static final int Widget_Quantum_Light_Button_Toggle = 16974491; // 0x103029b
- field public static final int Widget_Quantum_Light_CalendarView = 16974496; // 0x10302a0
- field public static final int Widget_Quantum_Light_CheckedTextView = 16974497; // 0x10302a1
- field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974498; // 0x10302a2
- field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974499; // 0x10302a3
- field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974500; // 0x10302a4
- field public static final int Widget_Quantum_Light_DropDownItem = 16974501; // 0x10302a5
- field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974502; // 0x10302a6
- field public static final int Widget_Quantum_Light_EditText = 16974503; // 0x10302a7
- field public static final int Widget_Quantum_Light_ExpandableListView = 16974504; // 0x10302a8
- field public static final int Widget_Quantum_Light_FastScroll = 16974505; // 0x10302a9
- field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974506; // 0x10302aa
- field public static final int Widget_Quantum_Light_GridView = 16974507; // 0x10302ab
- field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974508; // 0x10302ac
- field public static final int Widget_Quantum_Light_ImageButton = 16974509; // 0x10302ad
- field public static final int Widget_Quantum_Light_ListPopupWindow = 16974510; // 0x10302ae
- field public static final int Widget_Quantum_Light_ListView = 16974511; // 0x10302af
- field public static final int Widget_Quantum_Light_ListView_DropDown = 16974512; // 0x10302b0
- field public static final int Widget_Quantum_Light_MediaRouteButton = 16974513; // 0x10302b1
- field public static final int Widget_Quantum_Light_PopupMenu = 16974514; // 0x10302b2
- field public static final int Widget_Quantum_Light_PopupWindow = 16974515; // 0x10302b3
- field public static final int Widget_Quantum_Light_ProgressBar = 16974516; // 0x10302b4
- field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974517; // 0x10302b5
- field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974518; // 0x10302b6
- field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974519; // 0x10302b7
- field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974520; // 0x10302b8
- field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974521; // 0x10302b9
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974522; // 0x10302ba
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974523; // 0x10302bb
- field public static final int Widget_Quantum_Light_RatingBar = 16974524; // 0x10302bc
- field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974525; // 0x10302bd
- field public static final int Widget_Quantum_Light_RatingBar_Small = 16974526; // 0x10302be
- field public static final int Widget_Quantum_Light_ScrollView = 16974527; // 0x10302bf
- field public static final int Widget_Quantum_Light_SeekBar = 16974528; // 0x10302c0
- field public static final int Widget_Quantum_Light_SegmentedButton = 16974529; // 0x10302c1
- field public static final int Widget_Quantum_Light_Spinner = 16974531; // 0x10302c3
- field public static final int Widget_Quantum_Light_StackView = 16974530; // 0x10302c2
- field public static final int Widget_Quantum_Light_Tab = 16974532; // 0x10302c4
- field public static final int Widget_Quantum_Light_TabWidget = 16974533; // 0x10302c5
- field public static final int Widget_Quantum_Light_TextView = 16974534; // 0x10302c6
- field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974535; // 0x10302c7
- field public static final int Widget_Quantum_Light_WebTextView = 16974536; // 0x10302c8
- field public static final int Widget_Quantum_Light_WebView = 16974537; // 0x10302c9
- field public static final int Widget_Quantum_ListPopupWindow = 16974450; // 0x1030272
- field public static final int Widget_Quantum_ListView = 16974451; // 0x1030273
- field public static final int Widget_Quantum_ListView_DropDown = 16974452; // 0x1030274
- field public static final int Widget_Quantum_MediaRouteButton = 16974453; // 0x1030275
- field public static final int Widget_Quantum_PopupMenu = 16974454; // 0x1030276
- field public static final int Widget_Quantum_PopupWindow = 16974455; // 0x1030277
- field public static final int Widget_Quantum_ProgressBar = 16974456; // 0x1030278
- field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974457; // 0x1030279
- field public static final int Widget_Quantum_ProgressBar_Large = 16974458; // 0x103027a
- field public static final int Widget_Quantum_ProgressBar_Small = 16974459; // 0x103027b
- field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974460; // 0x103027c
- field public static final int Widget_Quantum_RatingBar = 16974461; // 0x103027d
- field public static final int Widget_Quantum_RatingBar_Indicator = 16974462; // 0x103027e
- field public static final int Widget_Quantum_RatingBar_Small = 16974463; // 0x103027f
- field public static final int Widget_Quantum_ScrollView = 16974464; // 0x1030280
- field public static final int Widget_Quantum_SeekBar = 16974465; // 0x1030281
- field public static final int Widget_Quantum_SegmentedButton = 16974466; // 0x1030282
- field public static final int Widget_Quantum_Spinner = 16974468; // 0x1030284
- field public static final int Widget_Quantum_StackView = 16974467; // 0x1030283
- field public static final int Widget_Quantum_Tab = 16974469; // 0x1030285
- field public static final int Widget_Quantum_TabWidget = 16974470; // 0x1030286
- field public static final int Widget_Quantum_TextView = 16974471; // 0x1030287
- field public static final int Widget_Quantum_TextView_SpinnerItem = 16974472; // 0x1030288
- field public static final int Widget_Quantum_WebTextView = 16974473; // 0x1030289
- field public static final int Widget_Quantum_WebView = 16974474; // 0x103028a
+ field public static final int Widget_Quantum_CalendarView = 16974433; // 0x1030261
+ field public static final int Widget_Quantum_CheckedTextView = 16974434; // 0x1030262
+ field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974435; // 0x1030263
+ field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974436; // 0x1030264
+ field public static final int Widget_Quantum_CompoundButton_Star = 16974437; // 0x1030265
+ field public static final int Widget_Quantum_DatePicker = 16974438; // 0x1030266
+ field public static final int Widget_Quantum_DropDownItem = 16974439; // 0x1030267
+ field public static final int Widget_Quantum_DropDownItem_Spinner = 16974440; // 0x1030268
+ field public static final int Widget_Quantum_EditText = 16974441; // 0x1030269
+ field public static final int Widget_Quantum_ExpandableListView = 16974442; // 0x103026a
+ field public static final int Widget_Quantum_FastScroll = 16974443; // 0x103026b
+ field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974444; // 0x103026c
+ field public static final int Widget_Quantum_GridView = 16974445; // 0x103026d
+ field public static final int Widget_Quantum_HorizontalScrollView = 16974446; // 0x103026e
+ field public static final int Widget_Quantum_ImageButton = 16974447; // 0x103026f
+ field public static final int Widget_Quantum_Light = 16974473; // 0x1030289
+ field public static final int Widget_Quantum_Light_ActionBar = 16974474; // 0x103028a
+ field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974475; // 0x103028b
+ field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974476; // 0x103028c
+ field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974477; // 0x103028d
+ field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974478; // 0x103028e
+ field public static final int Widget_Quantum_Light_ActionButton = 16974479; // 0x103028f
+ field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974480; // 0x1030290
+ field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974481; // 0x1030291
+ field public static final int Widget_Quantum_Light_ActionMode = 16974482; // 0x1030292
+ field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974483; // 0x1030293
+ field public static final int Widget_Quantum_Light_Button = 16974484; // 0x1030294
+ field public static final int Widget_Quantum_Light_ButtonBar = 16974490; // 0x103029a
+ field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974491; // 0x103029b
+ field public static final int Widget_Quantum_Light_Button_Borderless = 16974485; // 0x1030295
+ field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974486; // 0x1030296
+ field public static final int Widget_Quantum_Light_Button_Inset = 16974487; // 0x1030297
+ field public static final int Widget_Quantum_Light_Button_Small = 16974488; // 0x1030298
+ field public static final int Widget_Quantum_Light_Button_Toggle = 16974489; // 0x1030299
+ field public static final int Widget_Quantum_Light_CalendarView = 16974492; // 0x103029c
+ field public static final int Widget_Quantum_Light_CheckedTextView = 16974493; // 0x103029d
+ field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974494; // 0x103029e
+ field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974495; // 0x103029f
+ field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974496; // 0x10302a0
+ field public static final int Widget_Quantum_Light_DropDownItem = 16974497; // 0x10302a1
+ field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974498; // 0x10302a2
+ field public static final int Widget_Quantum_Light_EditText = 16974499; // 0x10302a3
+ field public static final int Widget_Quantum_Light_ExpandableListView = 16974500; // 0x10302a4
+ field public static final int Widget_Quantum_Light_FastScroll = 16974501; // 0x10302a5
+ field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974502; // 0x10302a6
+ field public static final int Widget_Quantum_Light_GridView = 16974503; // 0x10302a7
+ field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974504; // 0x10302a8
+ field public static final int Widget_Quantum_Light_ImageButton = 16974505; // 0x10302a9
+ field public static final int Widget_Quantum_Light_ListPopupWindow = 16974506; // 0x10302aa
+ field public static final int Widget_Quantum_Light_ListView = 16974507; // 0x10302ab
+ field public static final int Widget_Quantum_Light_ListView_DropDown = 16974508; // 0x10302ac
+ field public static final int Widget_Quantum_Light_MediaRouteButton = 16974509; // 0x10302ad
+ field public static final int Widget_Quantum_Light_PopupMenu = 16974510; // 0x10302ae
+ field public static final int Widget_Quantum_Light_PopupWindow = 16974511; // 0x10302af
+ field public static final int Widget_Quantum_Light_ProgressBar = 16974512; // 0x10302b0
+ field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974513; // 0x10302b1
+ field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974514; // 0x10302b2
+ field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974515; // 0x10302b3
+ field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974516; // 0x10302b4
+ field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974517; // 0x10302b5
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974518; // 0x10302b6
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974519; // 0x10302b7
+ field public static final int Widget_Quantum_Light_RatingBar = 16974520; // 0x10302b8
+ field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974521; // 0x10302b9
+ field public static final int Widget_Quantum_Light_RatingBar_Small = 16974522; // 0x10302ba
+ field public static final int Widget_Quantum_Light_ScrollView = 16974523; // 0x10302bb
+ field public static final int Widget_Quantum_Light_SeekBar = 16974524; // 0x10302bc
+ field public static final int Widget_Quantum_Light_SegmentedButton = 16974525; // 0x10302bd
+ field public static final int Widget_Quantum_Light_Spinner = 16974527; // 0x10302bf
+ field public static final int Widget_Quantum_Light_StackView = 16974526; // 0x10302be
+ field public static final int Widget_Quantum_Light_Tab = 16974528; // 0x10302c0
+ field public static final int Widget_Quantum_Light_TabWidget = 16974529; // 0x10302c1
+ field public static final int Widget_Quantum_Light_TextView = 16974530; // 0x10302c2
+ field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974531; // 0x10302c3
+ field public static final int Widget_Quantum_Light_WebTextView = 16974532; // 0x10302c4
+ field public static final int Widget_Quantum_Light_WebView = 16974533; // 0x10302c5
+ field public static final int Widget_Quantum_ListPopupWindow = 16974448; // 0x1030270
+ field public static final int Widget_Quantum_ListView = 16974449; // 0x1030271
+ field public static final int Widget_Quantum_ListView_DropDown = 16974450; // 0x1030272
+ field public static final int Widget_Quantum_MediaRouteButton = 16974451; // 0x1030273
+ field public static final int Widget_Quantum_PopupMenu = 16974452; // 0x1030274
+ field public static final int Widget_Quantum_PopupWindow = 16974453; // 0x1030275
+ field public static final int Widget_Quantum_ProgressBar = 16974454; // 0x1030276
+ field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974455; // 0x1030277
+ field public static final int Widget_Quantum_ProgressBar_Large = 16974456; // 0x1030278
+ field public static final int Widget_Quantum_ProgressBar_Small = 16974457; // 0x1030279
+ field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974458; // 0x103027a
+ field public static final int Widget_Quantum_RatingBar = 16974459; // 0x103027b
+ field public static final int Widget_Quantum_RatingBar_Indicator = 16974460; // 0x103027c
+ field public static final int Widget_Quantum_RatingBar_Small = 16974461; // 0x103027d
+ field public static final int Widget_Quantum_ScrollView = 16974462; // 0x103027e
+ field public static final int Widget_Quantum_SeekBar = 16974463; // 0x103027f
+ field public static final int Widget_Quantum_SegmentedButton = 16974464; // 0x1030280
+ field public static final int Widget_Quantum_Spinner = 16974466; // 0x1030282
+ field public static final int Widget_Quantum_StackView = 16974465; // 0x1030281
+ field public static final int Widget_Quantum_Tab = 16974467; // 0x1030283
+ field public static final int Widget_Quantum_TabWidget = 16974468; // 0x1030284
+ field public static final int Widget_Quantum_TextView = 16974469; // 0x1030285
+ field public static final int Widget_Quantum_TextView_SpinnerItem = 16974470; // 0x1030286
+ field public static final int Widget_Quantum_WebTextView = 16974471; // 0x1030287
+ field public static final int Widget_Quantum_WebView = 16974472; // 0x1030288
field public static final int Widget_RatingBar = 16973857; // 0x1030021
field public static final int Widget_ScrollView = 16973869; // 0x103002d
field public static final int Widget_SeekBar = 16973856; // 0x1030020
@@ -12221,6 +12217,14 @@
field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_MODE;
}
+ public final class ColorSpaceTransform {
+ ctor public ColorSpaceTransform(android.hardware.camera2.Rational[]);
+ ctor public ColorSpaceTransform(int[]);
+ method public void copyElements(android.hardware.camera2.Rational[], int);
+ method public void copyElements(int[], int);
+ method public android.hardware.camera2.Rational getElement(int, int);
+ }
+
public final class Face {
method public android.graphics.Rect getBounds();
method public int getId();
@@ -12233,18 +12237,83 @@
field public static final int SCORE_MIN = 1; // 0x1
}
+ public final class LensShadingMap {
+ method public void copyGainFactors(float[], int);
+ method public int getColumnCount();
+ method public float getGainFactor(int, int, int);
+ method public int getGainFactorCount();
+ method public android.hardware.camera2.RggbChannelVector getGainFactorVector(int, int);
+ method public int getRowCount();
+ field public static final float MINIMUM_GAIN_FACTOR = 1.0f;
+ }
+
+ public final class MeteringRectangle {
+ ctor public MeteringRectangle(int, int, int, int, int);
+ ctor public MeteringRectangle(android.graphics.Point, android.util.Size, int);
+ ctor public MeteringRectangle(android.graphics.Rect, int);
+ method public boolean equals(android.hardware.camera2.MeteringRectangle);
+ method public int getHeight();
+ method public int getMeteringWeight();
+ method public android.graphics.Rect getRect();
+ method public android.util.Size getSize();
+ method public android.graphics.Point getUpperLeftPoint();
+ method public int getWidth();
+ method public int getX();
+ method public int getY();
+ }
+
public final class Rational {
ctor public Rational(int, int);
method public int getDenominator();
method public int getNumerator();
}
+ public final class RggbChannelVector {
+ ctor public RggbChannelVector(float, float, float, float);
+ method public void copyTo(float[], int);
+ method public float getBlue();
+ method public float getComponent(int);
+ method public float getGreenEven();
+ method public float getGreenOdd();
+ method public final float getRed();
+ field public static final int BLUE = 3; // 0x3
+ field public static final int COUNT = 4; // 0x4
+ field public static final int GREEN_EVEN = 1; // 0x1
+ field public static final int GREEN_ODD = 2; // 0x2
+ field public static final int RED = 0; // 0x0
+ }
+
public final class Size {
ctor public Size(int, int);
method public final int getHeight();
method public final int getWidth();
}
+ public final class StreamConfigurationMap {
+ method public final int[] getOutputFormats();
+ method public long getOutputMinFrameDuration(int, android.util.Size);
+ method public long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
+ method public android.util.Size[] getOutputSizes(java.lang.Class<T>);
+ method public android.util.Size[] getOutputSizes(int);
+ method public long getOutputStallDuration(int, android.util.Size);
+ method public long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
+ method public boolean isOutputSupportedFor(int);
+ method public static boolean isOutputSupportedFor(java.lang.Class<T>);
+ method public boolean isOutputSupportedFor(android.view.Surface);
+ }
+
+ public final class TonemapCurve {
+ method public void copyColorCurve(int, float[], int);
+ method public android.graphics.PointF getPoint(int, int);
+ method public int getPointCount(int);
+ field public static final int CHANNEL_BLUE = 2; // 0x2
+ field public static final int CHANNEL_GREEN = 1; // 0x1
+ field public static final int CHANNEL_RED = 0; // 0x0
+ field public static final float LEVEL_BLACK = 0.0f;
+ field public static final float LEVEL_WHITE = 1.0f;
+ field public static final int POINT_SIZE = 2; // 0x2
+ }
+
}
package android.hardware.display {
@@ -28713,6 +28782,25 @@
method public void set(T, V);
}
+ public final class Range {
+ ctor public Range(T, T);
+ method public static android.util.Range<T> create(T, T);
+ method public T getLower();
+ method public T getUpper();
+ }
+
+ public final class Size {
+ ctor public Size(int, int);
+ method public int getHeight();
+ method public int getWidth();
+ }
+
+ public final class SizeF {
+ ctor public SizeF(float, float);
+ method public float getHeight();
+ method public float getWidth();
+ }
+
public class SparseArray implements java.lang.Cloneable {
ctor public SparseArray();
ctor public SparseArray(int);
@@ -32697,6 +32785,16 @@
package android.webkit {
+ public abstract interface ClientCertRequest {
+ method public abstract void cancel();
+ method public abstract java.lang.String getHost();
+ method public abstract java.lang.String[] getKeyTypes();
+ method public abstract int getPort();
+ method public abstract java.security.Principal[] getPrincipals();
+ method public abstract void ignore();
+ method public abstract void proceed(java.security.PrivateKey, java.security.cert.X509Certificate[]);
+ }
+
public class ConsoleMessage {
ctor public ConsoleMessage(java.lang.String, java.lang.String, int, android.webkit.ConsoleMessage.MessageLevel);
method public int lineNumber();
@@ -33087,6 +33185,7 @@
method public deprecated boolean canZoomOut();
method public deprecated android.graphics.Picture capturePicture();
method public void clearCache(boolean);
+ method public static void clearClientCertPreferences(java.lang.Runnable);
method public void clearFormData();
method public void clearHistory();
method public void clearMatches();
@@ -33203,6 +33302,7 @@
method public void onLoadResource(android.webkit.WebView, java.lang.String);
method public void onPageFinished(android.webkit.WebView, java.lang.String);
method public void onPageStarted(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
+ method public void onReceivedClientCertRequest(android.webkit.WebView, android.webkit.ClientCertRequest);
method public void onReceivedError(android.webkit.WebView, int, java.lang.String, java.lang.String);
method public void onReceivedHttpAuthRequest(android.webkit.WebView, android.webkit.HttpAuthHandler, java.lang.String, java.lang.String);
method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index bb290af..9d0e0e1 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -192,8 +192,9 @@
*
* <p>The camera device will query each Surface's size and formats upon this
* call, so they must be set to a valid setting at this time (in particular:
- * if the format is user-visible, it must be one of android.scaler.availableFormats;
- * and the size must be one of android.scaler.available[Processed|Jpeg]Sizes).</p>
+ * if the format is user-visible, it must be one of
+ * {@link StreamConfigurationMap#getOutputFormats}; and the size must be one of
+ * {@link StreamConfigurationMap#getOutputSizes(int)}).</p>
*
* <p>When this method is called with valid Surfaces, the device will transition to the {@link
* StateListener#onBusy busy state}. Once configuration is complete, the device will transition
@@ -239,6 +240,9 @@
* @see StateListener#onUnconfigured
* @see #stopRepeating
* @see #flush
+ * @see StreamConfigurationMap#getOutputFormats()
+ * @see StreamConfigurationMap#getOutputSizes(int)
+ * @see StreamConfigurationMap#getOutputSizes(Class)
*/
public void configureOutputs(List<Surface> outputs) throws CameraAccessException;
diff --git a/core/java/android/hardware/camera2/ColorSpaceTransform.java b/core/java/android/hardware/camera2/ColorSpaceTransform.java
new file mode 100644
index 0000000..9912e4b
--- /dev/null
+++ b/core/java/android/hardware/camera2/ColorSpaceTransform.java
@@ -0,0 +1,239 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class for describing a 3x3 matrix of {@link Rational} values in row-major order.
+ *
+ * <p>This matrix maps a transform from one color space to another. For the particular color space
+ * source and target, see the appropriate camera metadata documentation for the key that provides
+ * this value.</p>
+ *
+ * @see CameraMetadata
+ */
+public final class ColorSpaceTransform {
+
+ /** The number of rows in this matrix. */
+ private static final int ROWS = 3;
+
+ /** The number of columns in this matrix. */
+ private static final int COLUMNS = 3;
+
+ /** The number of total Rational elements in this matrix. */
+ private static final int COUNT = ROWS * COLUMNS;
+
+ /** Number of int elements in a rational. */
+ private static final int RATIONAL_SIZE = 2;
+
+ /** Numerator offset inside a rational (pair). */
+ private static final int OFFSET_NUMERATOR = 0;
+
+ /** Denominator offset inside a rational (pair). */
+ private static final int OFFSET_DENOMINATOR = 1;
+
+ /** Number of int elements in this matrix. */
+ private static final int COUNT_INT = ROWS * COLUMNS * RATIONAL_SIZE;
+
+ /**
+ * Create a new immutable {@link ColorSpaceTransform} instance from a {@link Rational} array.
+ *
+ * <p>The elements must be stored in a row-major order.</p>
+ *
+ * @param elements An array of {@code 9} elements
+ *
+ * @throws IllegalArgumentException
+ * if the count of {@code elements} is not {@code 9}
+ * @throws NullPointerException
+ * if {@code elements} or any sub-element is {@code null}
+ */
+ public ColorSpaceTransform(Rational[] elements) {
+
+ checkNotNull(elements, "elements must not be null");
+ if (elements.length != COUNT) {
+ throw new IllegalArgumentException("elements must be " + COUNT + " length");
+ }
+
+ mElements = new int[COUNT_INT];
+
+ for (int i = 0; i < elements.length; ++i) {
+ checkNotNull(elements, "element[" + i + "] must not be null");
+ mElements[i * RATIONAL_SIZE + OFFSET_NUMERATOR] = elements[i].getNumerator();
+ mElements[i * RATIONAL_SIZE + OFFSET_DENOMINATOR] = elements[i].getDenominator();
+ }
+ }
+
+ /**
+ * Create a new immutable {@link ColorSpaceTransform} instance from an {@code int} array.
+ *
+ * <p>The elements must be stored in a row-major order. Each rational is stored
+ * contiguously as a {@code (numerator, denominator)} pair.</p>
+ *
+ * <p>In particular:<pre>{@code
+ * int[] elements = new int[
+ * N11, D11, N12, D12, N13, D13,
+ * N21, D21, N22, D22, N23, D23,
+ * N31, D31, N32, D32, N33, D33
+ * ];
+ *
+ * new ColorSpaceTransform(elements)}</pre>
+ *
+ * where {@code Nij} and {@code Dij} is the numerator and denominator for row {@code i} and
+ * column {@code j}.</p>
+ *
+ * @param elements An array of {@code 18} elements
+ *
+ * @throws IllegalArgumentException
+ * if the count of {@code elements} is not {@code 18}
+ * @throws NullPointerException
+ * if {@code elements} is {@code null}
+ */
+ public ColorSpaceTransform(int[] elements) {
+ checkNotNull(elements, "elements must not be null");
+ if (elements.length != COUNT_INT) {
+ throw new IllegalArgumentException("elements must be " + COUNT_INT + " length");
+ }
+
+ for (int i = 0; i < elements.length; ++i) {
+ checkNotNull(elements, "element " + i + " must not be null");
+ }
+
+ mElements = Arrays.copyOf(elements, elements.length);
+ }
+
+ /**
+ * Get an element of this matrix by its row and column.
+ *
+ * <p>The rows must be within the range [0, 3),
+ * and the column must be within the range [0, 3).</p>
+ *
+ * @return element (non-{@code null})
+ *
+ * @throws IllegalArgumentException if column or row was out of range
+ */
+ public Rational getElement(int column, int row) {
+ if (column < 0 || column >= COLUMNS) {
+ throw new IllegalArgumentException("column out of range");
+ } else if (row < 0 || row >= ROWS) {
+ throw new IllegalArgumentException("row out of range");
+ }
+
+ int numerator = mElements[row * ROWS * RATIONAL_SIZE + column + OFFSET_NUMERATOR];
+ int denominator = mElements[row * ROWS * RATIONAL_SIZE + column + OFFSET_DENOMINATOR];
+
+ return new Rational(numerator, denominator);
+ }
+
+ /**
+ * Copy the {@link Rational} elements in row-major order from this matrix into the destination.
+ *
+ * @param destination
+ * an array big enough to hold at least {@code 9} elements after the
+ * {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ */
+ public void copyElements(Rational[] destination, int offset) {
+ checkArgumentNonnegative(offset, "offset must not be negative");
+ checkNotNull(destination, "destination must not be null");
+ if (destination.length + offset < COUNT) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ for (int i = 0, j = 0; i < COUNT; ++i, j += RATIONAL_SIZE) {
+ int numerator = mElements[j + OFFSET_NUMERATOR];
+ int denominator = mElements[j + OFFSET_DENOMINATOR];
+
+ destination[i + offset] = new Rational(numerator, denominator);
+ }
+ }
+
+ /**
+ * Copy the {@link Rational} elements in row-major order from this matrix into the destination.
+ *
+ * <p>Each element is stored as a contiguous rational packed as a
+ * {@code (numerator, denominator)} pair of ints, identical to the
+ * {@link ColorSpaceTransform#ColorSpaceTransform(int[]) constructor}.</p>
+ *
+ * @param destination
+ * an array big enough to hold at least {@code 18} elements after the
+ * {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ *
+ * @see ColorSpaceTransform#ColorSpaceTransform(int[])
+ */
+ public void copyElements(int[] destination, int offset) {
+ checkArgumentNonnegative(offset, "offset must not be negative");
+ checkNotNull(destination, "destination must not be null");
+ if (destination.length + offset < COUNT_INT) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ // Manual copy faster than System#arraycopy for very small loops
+ for (int i = 0; i < COUNT_INT; ++i) {
+ destination[i + offset] = mElements[i];
+ }
+ }
+
+ /**
+ * Check if this {@link ColorSpaceTransform} is equal to another {@link ColorSpaceTransform}.
+ *
+ * <p>Two color space transforms are equal if and only if all of their elements are
+ * {@link Object#equals equal}.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ColorSpaceTransform) {
+ final ColorSpaceTransform other = (ColorSpaceTransform) obj;
+ return Arrays.equals(mElements, other.mElements);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mElements);
+ }
+
+ private final int[] mElements;
+};
diff --git a/core/java/android/hardware/camera2/LensShadingMap.java b/core/java/android/hardware/camera2/LensShadingMap.java
new file mode 100644
index 0000000..2c224f64
--- /dev/null
+++ b/core/java/android/hardware/camera2/LensShadingMap.java
@@ -0,0 +1,243 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import static android.hardware.camera2.RggbChannelVector.*;
+
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class for describing a {@code 4 x N x M} lens shading map of floats.
+ *
+ * @see CameraCharacteristics#LENS_SHADING_MAP
+ */
+public final class LensShadingMap {
+
+ /**
+ * The smallest gain factor in this map.
+ *
+ * <p>All values in this map will be at least this large.</p>
+ */
+ public static final float MINIMUM_GAIN_FACTOR = 1.0f;
+
+ /**
+ * Create a new immutable LensShadingMap instance.
+ *
+ * <p>The elements must be stored in a row-major order (fully packed).</p>
+ *
+ * <p>This constructor takes over the array; do not write to the array afterwards.</p>
+ *
+ * @param elements
+ * An array of elements whose length is
+ * {@code RggbChannelVector.COUNT * rows * columns}
+ *
+ * @throws IllegalArgumentException
+ * if the {@code elements} array length is invalid,
+ * if any of the subelems are not finite or less than {@value #MINIMUM_GAIN_FACTOR},
+ * or if rows or columns is not positive
+ * @throws NullPointerException
+ * if {@code elements} is {@code null}
+ *
+ * @hide
+ */
+ public LensShadingMap(final float[] elements, final int rows, final int columns) {
+
+ mRows = checkArgumentPositive(rows, "rows must be positive");
+ mColumns = checkArgumentPositive(rows, "columns must be positive");
+ mElements = checkNotNull(elements, "elements must not be null");
+
+ if (elements.length != getGainFactorCount()) {
+ throw new IllegalArgumentException("elements must be " + getGainFactorCount() +
+ " length");
+ }
+
+ // Every element must be finite and >= 1.0f
+ checkArrayElementsInRange(elements, MINIMUM_GAIN_FACTOR, Float.MAX_VALUE, "elements");
+ }
+
+ /**
+ * Get the number of rows in this map.
+ */
+ public int getRowCount() {
+ return mRows;
+ }
+
+ /**
+ * Get the number of columns in this map.
+ */
+ public int getColumnCount() {
+ return mColumns;
+ }
+
+ /**
+ * Get the total number of gain factors in this map.
+ *
+ * <p>A single gain factor contains exactly one color channel.
+ * Use with {@link #copyGainFactors} to allocate a large-enough array.</p>
+ */
+ public int getGainFactorCount() {
+ return mRows * mColumns * COUNT;
+ }
+
+ /**
+ * Get a single color channel gain factor from this lens shading map by its row and column.
+ *
+ * <p>The rows must be within the range [0, {@link #getRowCount}),
+ * the column must be within the range [0, {@link #getColumnCount}),
+ * and the color channel must be within the range [0, {@value RggbChannelVector#COUNT}).</p>
+ *
+ * <p>The channel order is {@code [R, Geven, Godd, B]}, where
+ * {@code Geven} is the green channel for the even rows of a Bayer pattern, and
+ * {@code Godd} is the odd rows.
+ * </p>
+ *
+ * @param colorChannel color channel from {@code [R, Geven, Godd, B]}
+ * @param column within the range [0, {@link #getColumnCount})
+ * @param row within the range [0, {@link #getRowCount})
+ *
+ * @return a gain factor >= {@value #MINIMUM_GAIN_FACTOR}
+ *
+ * @throws IllegalArgumentException if any of the parameters was out of range
+ *
+ * @see #RED
+ * @see #GREEN_EVEN
+ * @see #GREEN_ODD
+ * @see #BLUE
+ * @see #getRowCount
+ * @see #getColumnCount
+ */
+ public float getGainFactor(final int colorChannel, final int column, final int row) {
+ if (colorChannel < 0 || colorChannel > COUNT) {
+ throw new IllegalArgumentException("colorChannel out of range");
+ } else if (column < 0 || column >= mColumns) {
+ throw new IllegalArgumentException("column out of range");
+ } else if (row < 0 || row >= mRows) {
+ throw new IllegalArgumentException("row out of range");
+ }
+
+ return mElements[colorChannel + (row * mColumns + column) * COUNT ];
+ }
+
+ /**
+ * Get a gain factor vector from this lens shading map by its row and column.
+ *
+ * <p>The rows must be within the range [0, {@link #getRowCount}),
+ * the column must be within the range [0, {@link #getColumnCount}).</p>
+ *
+ * @param column within the range [0, {@link #getColumnCount})
+ * @param row within the range [0, {@link #getRowCount})
+ *
+ * @return an {@link RggbChannelVector} where each gain factor >= {@value #MINIMUM_GAIN_FACTOR}
+ *
+ * @throws IllegalArgumentException if any of the parameters was out of range
+ *
+ * @see #getRowCount
+ * @see #getColumnCount
+ */
+ public RggbChannelVector getGainFactorVector(final int column, final int row) {
+ if (column < 0 || column >= mColumns) {
+ throw new IllegalArgumentException("column out of range");
+ } else if (row < 0 || row >= mRows) {
+ throw new IllegalArgumentException("row out of range");
+ }
+
+ final int offset = (row * mColumns + column) * COUNT;
+
+ final float red =
+ mElements[RED + offset];
+ final float greenEven =
+ mElements[GREEN_EVEN + offset];
+ final float greenOdd =
+ mElements[GREEN_ODD + offset];
+ final float blue =
+ mElements[BLUE + offset];
+
+ return new RggbChannelVector(red, greenEven, greenOdd, blue);
+ }
+
+ /**
+ * Copy all gain factors in row-major order from this lens shading map into the destination.
+ *
+ * <p>Each gain factor will be >= {@link #MINIMUM_GAIN_FACTOR}.</p>
+ *
+ * @param destination
+ * an array big enough to hold at least {@link RggbChannelVector#COUNT}
+ * elements after the {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws IllegalArgumentException
+ * If offset was negative
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ *
+ * @see CaptureResult#STATISTICS_LENS_SHADING_MAP
+ */
+ public void copyGainFactors(final float[] destination, final int offset) {
+ checkArgumentNonnegative(offset, "offset must not be negative");
+ checkNotNull(destination, "destination must not be null");
+ if (destination.length + offset < getGainFactorCount()) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ System.arraycopy(mElements, /*srcPos*/0, destination, offset, getGainFactorCount());
+ }
+
+ /**
+ * Check if this LensShadingMap is equal to another LensShadingMap.
+ *
+ * <p>Two lens shading maps are equal if and only if they have the same rows/columns,
+ * and all of their elements are {@link Object#equals equal}.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof LensShadingMap) {
+ final LensShadingMap other = (LensShadingMap) obj;
+ return mRows == other.mRows
+ && mColumns == other.mColumns
+ && Arrays.equals(mElements, other.mElements);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ int elemsHash = HashCodeHelpers.hashCode(mElements);
+ return HashCodeHelpers.hashCode(mRows, mColumns, elemsHash);
+ }
+
+
+ private final int mRows;
+ private final int mColumns;
+ private final float[] mElements;
+};
diff --git a/core/java/android/hardware/camera2/MeteringRectangle.java b/core/java/android/hardware/camera2/MeteringRectangle.java
new file mode 100644
index 0000000..ff7a745
--- /dev/null
+++ b/core/java/android/hardware/camera2/MeteringRectangle.java
@@ -0,0 +1,224 @@
+/*
+ * 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.hardware.camera2;
+
+import android.util.Size;
+import static com.android.internal.util.Preconditions.*;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+/**
+ * An immutable class to represent a rectangle {@code (x,y, width, height)} with an
+ * additional weight component.
+ *
+ * </p>The rectangle is defined to be inclusive of the specified coordinates.</p>
+ *
+ * <p>When used with a {@link CaptureRequest}, the coordinate system is based on the active pixel
+ * array, with {@code (0,0)} being the top-left pixel in the
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE active pixel array}, and
+ * {@code (android.sensor.info.activeArraySize.width - 1,
+ * android.sensor.info.activeArraySize.height - 1)}
+ * being the bottom-right pixel in the active pixel array.
+ * </p>
+ *
+ * <p>The metering weight is nonnegative.</p>
+ */
+public final class MeteringRectangle {
+
+ private final int mX;
+ private final int mY;
+ private final int mWidth;
+ private final int mHeight;
+ private final int mWeight;
+
+ /**
+ * Create a new metering rectangle.
+ *
+ * @param x coordinate >= 0
+ * @param y coordinate >= 0
+ * @param width width >= 0
+ * @param height height >= 0
+ * @param meteringWeight weight >= 0
+ *
+ * @throws IllegalArgumentException if any of the parameters were non-negative
+ */
+ public MeteringRectangle(int x, int y, int width, int height, int meteringWeight) {
+ mX = checkArgumentNonnegative(x, "x must be nonnegative");
+ mY = checkArgumentNonnegative(y, "y must be nonnegative");
+ mWidth = checkArgumentNonnegative(width, "width must be nonnegative");
+ mHeight = checkArgumentNonnegative(height, "height must be nonnegative");
+ mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
+ }
+
+ /**
+ * Create a new metering rectangle.
+ *
+ * @param xy a non-{@code null} {@link Point} with both x,y >= 0
+ * @param dimensions a non-{@code null} {@link android.util.Size Size} with width, height >= 0
+ * @param meteringWeight weight >= 0
+ *
+ * @throws IllegalArgumentException if any of the parameters were non-negative
+ * @throws NullPointerException if any of the arguments were null
+ */
+ public MeteringRectangle(Point xy, Size dimensions, int meteringWeight) {
+ checkNotNull(xy, "xy must not be null");
+ checkNotNull(dimensions, "dimensions must not be null");
+
+ mX = checkArgumentNonnegative(xy.x, "x must be nonnegative");
+ mY = checkArgumentNonnegative(xy.y, "y must be nonnegative");
+ mWidth = checkArgumentNonnegative(dimensions.getWidth(), "width must be nonnegative");
+ mHeight = checkArgumentNonnegative(dimensions.getHeight(), "height must be nonnegative");
+ mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
+ }
+
+ /**
+ * Create a new metering rectangle.
+ *
+ * @param rect a non-{@code null} rectangle with all x,y,w,h dimensions >= 0
+ * @param meteringWeight weight >= 0
+ *
+ * @throws IllegalArgumentException if any of the parameters were non-negative
+ * @throws NullPointerException if any of the arguments were null
+ */
+ public MeteringRectangle(Rect rect, int meteringWeight) {
+ checkNotNull(rect, "rect must not be null");
+
+ mX = checkArgumentNonnegative(rect.left, "rect.left must be nonnegative");
+ mY = checkArgumentNonnegative(rect.top, "rect.top must be nonnegative");
+ mWidth = checkArgumentNonnegative(rect.width(), "rect.width must be nonnegative");
+ mHeight = checkArgumentNonnegative(rect.height(), "rect.height must be nonnegative");
+ mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
+ }
+
+ /**
+ * Return the X coordinate of the left side of the rectangle.
+ *
+ * @return x coordinate >= 0
+ */
+ public int getX() {
+ return mX;
+ }
+
+ /**
+ * Return the Y coordinate of the upper side of the rectangle.
+ *
+ * @return y coordinate >= 0
+ */
+ public int getY() {
+ return mY;
+ }
+
+ /**
+ * Return the width of the rectangle.
+ *
+ * @return width >= 0
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Return the height of the rectangle.
+ *
+ * @return height >= 0
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Return the metering weight of the rectangle.
+ *
+ * @return weight >= 0
+ */
+ public int getMeteringWeight() {
+ return mWeight;
+ }
+
+ /**
+ * Convenience method to create the upper-left (X,Y) coordinate as a {@link Point}.
+ *
+ * @return {@code (x,y)} point with both x,y >= 0
+ */
+ public Point getUpperLeftPoint() {
+ return new Point(mX, mY);
+ }
+
+ /**
+ * Convenience method to create the size from this metering rectangle.
+ *
+ * <p>This strips away the X,Y,weight from the rectangle.</p>
+ *
+ * @return a Size with non-negative width and height
+ */
+ public Size getSize() {
+ return new Size(mWidth, mHeight);
+ }
+
+ /**
+ * Convenience method to create a {@link Rect} from this metering rectangle.
+ *
+ * <p>This strips away the weight from the rectangle.</p>
+ *
+ * @return a {@link Rect} with non-negative x1, y1, x2, y2
+ */
+ public Rect getRect() {
+ return new Rect(mX, mY, mX + mWidth, mY + mHeight);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(final Object other) {
+ if (other instanceof MeteringRectangle) {
+ return equals(other);
+ }
+ return false;
+ }
+
+ /**
+ * Compare two metering rectangles to see if they are equal.
+ *
+ * Two weighted rectangles are only considered equal if each of their components
+ * (x, y, width, height, weight) is respectively equal.
+ *
+ * @param other Another MeteringRectangle
+ *
+ * @return {@code true} if the metering rectangles are equal, {@code false} otherwise
+ */
+ public boolean equals(final MeteringRectangle other) {
+ if (other == null) {
+ return false;
+ }
+
+ return (mX == other.mX
+ && mY == other.mY
+ && mWidth == other.mWidth
+ && mHeight == other.mHeight
+ && mWidth == other.mWidth);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mX, mY, mWidth, mHeight, mWeight);
+ }
+}
diff --git a/core/java/android/hardware/camera2/ReprocessFormatsMap.java b/core/java/android/hardware/camera2/ReprocessFormatsMap.java
new file mode 100644
index 0000000..c6c59d4
--- /dev/null
+++ b/core/java/android/hardware/camera2/ReprocessFormatsMap.java
@@ -0,0 +1,258 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class to store the input to output formats
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP map} to be used for with
+ * camera image reprocessing.
+ *
+ * <p>
+ * The mapping of image formats that are supported by this camera device for input streams,
+ * to their corresponding output formats.</p>
+ *
+ * <p>
+ * Attempting to configure an input stream with output streams not listed as available in this map
+ * is not valid.
+ * </p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ *
+ * <!-- hide this until we expose input streams through public API -->
+ * @hide
+ */
+public final class ReprocessFormatsMap {
+ /**
+ * Create a new {@link ReprocessFormatsMap}
+ *
+ * <p>This value is encoded as a variable-size array-of-arrays.
+ * The inner array always contains {@code [format, length, ...]} where ... has length elements.
+ * An inner array is followed by another inner array if the total metadata entry size hasn't
+ * yet been exceeded.</p>
+ *
+ * <p>Entry must not be {@code null}. Empty array is acceptable.</p>
+ *
+ * <p>The entry array ownership is passed to this instance after construction; do not
+ * write to it afterwards.</p>
+ *
+ * @param entry Array of ints, not yet deserialized (not-null)
+ *
+ * @throws IllegalArgumentException
+ * if the data was poorly formatted
+ * (missing output format length or too few output formats)
+ * @throws NullPointerException
+ * if entry was null
+ *
+ * @hide
+ */
+ public ReprocessFormatsMap(final int[] entry) {
+ checkNotNull(entry, "entry must not be null");
+
+ int numInputs = 0;
+ int left = entry.length;
+ for (int i = 0; i < entry.length; ) {
+ final int format = entry[i];
+
+ left--;
+ i++;
+
+ if (left < 1) {
+ throw new IllegalArgumentException(
+ String.format("Input %x had no output format length listed", format));
+ }
+
+ final int length = entry[i];
+ left--;
+ i++;
+
+ if (length > 0) {
+ if (left < length) {
+ throw new IllegalArgumentException(
+ String.format(
+ "Input %x had too few output formats listed (actual: %d, " +
+ "expected: %d)", format, left, length));
+ }
+
+ i += length;
+ left -= length;
+ }
+
+ numInputs++;
+ }
+
+ mEntry = entry;
+ mInputCount = numInputs;
+ }
+
+ /**
+ * Get a list of all input image formats that can be used to reprocess an input
+ * stream into an output stream.
+ *
+ * <p>Use this input format to look up the available output formats with {@link #getOutputs}.
+ * </p>
+ *
+ * @return an array of inputs (possibly empty, but never {@code null})
+ *
+ * @see ImageFormat
+ * @see #getOutputs
+ */
+ public int[] getInputs() {
+ final int[] inputs = new int[mInputCount];
+
+ int left = mEntry.length;
+ for (int i = 0, j = 0; i < mEntry.length; j++) {
+ final int format = mEntry[i];
+
+ left--;
+ i++;
+
+ if (left < 1) {
+ throw new AssertionError(
+ String.format("Input %x had no output format length listed", format));
+ }
+ // TODO: check format is a valid input format
+
+ final int length = mEntry[i];
+ left--;
+ i++;
+
+ if (length > 0) {
+ if (left < length) {
+ throw new AssertionError(
+ String.format(
+ "Input %x had too few output formats listed (actual: %d, " +
+ "expected: %d)", format, left, length));
+ }
+
+ i += length;
+ left -= length;
+ }
+
+ // TODO: check output format is a valid output format
+
+ inputs[j] = format;
+ }
+
+ return inputs;
+ }
+
+ /**
+ * Get the list of output formats that can be reprocessed into from the input {@code format}.
+ *
+ * <p>The input {@code format} must be one of the formats returned by {@link #getInputs}.</p>
+ *
+ * @param format an input format
+ *
+ * @return list of output image formats
+ *
+ * @see ImageFormat
+ * @see #getInputs
+ */
+ public int[] getOutputs(final int format) {
+
+ int left = mEntry.length;
+ for (int i = 0; i < mEntry.length; ) {
+ final int inputFormat = mEntry[i];
+
+ left--;
+ i++;
+
+ if (left < 1) {
+ throw new AssertionError(
+ String.format("Input %x had no output format length listed", format));
+ }
+
+ final int length = mEntry[i];
+ left--;
+ i++;
+
+ if (length > 0) {
+ if (left < length) {
+ throw new AssertionError(
+ String.format(
+ "Input %x had too few output formats listed (actual: %d, " +
+ "expected: %d)", format, left, length));
+ }
+ }
+
+ if (inputFormat == format) {
+ int[] outputs = new int[length];
+
+ // Copying manually faster than System.arraycopy for small arrays
+ for (int k = 0; k < length; ++k) {
+ outputs[k] = mEntry[i + k];
+ }
+
+ return outputs;
+ }
+
+ i += length;
+ left -= length;
+
+ }
+
+ throw new IllegalArgumentException(
+ String.format("Input format %x was not one in #getInputs", format));
+ }
+
+ /**
+ * Check if this {@link ReprocessFormatsMap} is equal to another
+ * {@link ReprocessFormatsMap}.
+ *
+ * <p>These two objects are only equal if and only if each of the respective elements is equal.
+ * </p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ReprocessFormatsMap) {
+ final ReprocessFormatsMap other = (ReprocessFormatsMap) obj;
+ // Do not compare anything besides mEntry, since the rest of the values are derived
+ return Arrays.equals(mEntry, other.mEntry);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // Do not hash anything besides mEntry since the rest of the values are derived
+ return HashCodeHelpers.hashCode(mEntry);
+ }
+
+ private final int[] mEntry;
+ /*
+ * Dependent fields: values are derived from mEntry
+ */
+ private final int mInputCount;
+}
diff --git a/core/java/android/hardware/camera2/RggbChannelVector.java b/core/java/android/hardware/camera2/RggbChannelVector.java
new file mode 100644
index 0000000..80167c6
--- /dev/null
+++ b/core/java/android/hardware/camera2/RggbChannelVector.java
@@ -0,0 +1,199 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Immutable class to store a 4-element vector of floats indexable by a bayer RAW 2x2 pixel block.
+ */
+public final class RggbChannelVector {
+ /**
+ * The number of color channels in this vector.
+ */
+ public static final int COUNT = 4;
+
+ /** Red color channel in a bayer Raw pattern. */
+ public static final int RED = 0;
+
+ /** Green color channel in a bayer Raw pattern used by the even rows. */
+ public static final int GREEN_EVEN = 1;
+
+ /** Green color channel in a bayer Raw pattern used by the odd rows. */
+ public static final int GREEN_ODD = 2;
+
+ /** Blue color channel in a bayer Raw pattern. */
+ public static final int BLUE = 3;
+
+ /**
+ * Create a new {@link RggbChannelVector} from an RGGB 2x2 pixel.
+ *
+ * <p>All pixel values are considered normalized within {@code [0.0f, 1.0f]}
+ * (i.e. {@code 1.0f} could be linearized to {@code 255} if converting to a
+ * non-floating point pixel representation).</p>
+ *
+ * <p>All arguments must be finite; NaN and infinity is not allowed.</p>
+ *
+ * @param red red pixel
+ * @param greenEven green pixel (even row)
+ * @param greenOdd green pixel (odd row)
+ * @param blue blue pixel
+ *
+ * @throws IllegalArgumentException if any of the arguments were not finite
+ */
+ public RggbChannelVector(final float red, final float greenEven, final float greenOdd,
+ final float blue) {
+ mRed = checkArgumentFinite(red, "red");
+ mGreenEven = checkArgumentFinite(greenEven, "greenEven");
+ mGreenOdd = checkArgumentFinite(greenOdd, "greenOdd");
+ mBlue = checkArgumentFinite(blue, "blue");
+ }
+
+ /**
+ * Get the red component.
+ *
+ * @return a floating point value (guaranteed to be finite)
+ */
+ public final float getRed() {
+ return mRed;
+ }
+
+ /**
+ * Get the green (even rows) component.
+ *
+ * @return a floating point value (guaranteed to be finite)
+ */
+ public float getGreenEven() {
+ return mGreenEven;
+ }
+
+ /**
+ * Get the green (odd rows) component.
+ *
+ * @return a floating point value (guaranteed to be finite)
+ */
+ public float getGreenOdd() {
+ return mGreenOdd;
+ }
+
+ /**
+ * Get the blue component.
+ *
+ * @return a floating point value (guaranteed to be finite)
+ */
+ public float getBlue() {
+ return mBlue;
+ }
+
+ /**
+ * Get the component by the color channel index.
+ *
+ * <p>{@code colorChannel} must be one of {@link #RED}, {@link #GREEN_EVEN}, {@link #GREEN_ODD},
+ * {@link #BLUE}.</p>
+ *
+ * @param colorChannel greater or equal to {@code 0} and less than {@link #COUNT}
+ * @return a floating point value (guaranteed to be finite)
+ *
+ * @throws IllegalArgumentException if {@code colorChannel} was out of range
+ */
+ public float getComponent(final int colorChannel) {
+ if (colorChannel < 0 || colorChannel >= COUNT) {
+ throw new IllegalArgumentException("Color channel out of range");
+ }
+
+ switch (colorChannel) {
+ case RED:
+ return mRed;
+ case GREEN_EVEN:
+ return mGreenEven;
+ case GREEN_ODD:
+ return mGreenOdd;
+ case BLUE:
+ return mBlue;
+ default:
+ throw new AssertionError("Unhandled case " + colorChannel);
+ }
+ }
+
+ /**
+ * Copy the vector into the destination in the order {@code [R, Geven, Godd, B]}.
+ *
+ * @param destination
+ * an array big enough to hold at least {@value #COUNT} elements after the
+ * {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ *
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ */
+ public void copyTo(final float[] destination, final int offset) {
+ checkNotNull(destination, "destination must not be null");
+ if (destination.length + offset < COUNT) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ destination[offset + RED] = mRed;
+ destination[offset + GREEN_EVEN] = mGreenEven;
+ destination[offset + GREEN_ODD] = mGreenOdd;
+ destination[offset + BLUE] = mBlue;
+ }
+
+ /**
+ * Check if this {@link RggbChannelVector} is equal to another {@link RggbChannelVector}.
+ *
+ * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof RggbChannelVector) {
+ final RggbChannelVector other = (RggbChannelVector) obj;
+ return mRed == other.mRed &&
+ mGreenEven == other.mGreenEven &&
+ mGreenOdd == other.mGreenOdd &&
+ mBlue == other.mBlue;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Float.floatToIntBits(mRed) ^
+ Float.floatToIntBits(mGreenEven) ^
+ Float.floatToIntBits(mGreenOdd) ^
+ Float.floatToIntBits(mBlue);
+ }
+
+ private final float mRed;
+ private final float mGreenEven;
+ private final float mGreenOdd;
+ private final float mBlue;
+}
diff --git a/core/java/android/hardware/camera2/Size.java b/core/java/android/hardware/camera2/Size.java
index 45aaeae..9328a003 100644
--- a/core/java/android/hardware/camera2/Size.java
+++ b/core/java/android/hardware/camera2/Size.java
@@ -16,32 +16,55 @@
package android.hardware.camera2;
+// TODO: Delete this class, since it was moved to android.util as public API
+
/**
- * A simple immutable class for describing the dimensions of camera image
- * buffers.
+ * Immutable class for describing width and height dimensions in pixels.
+ *
+ * @hide
*/
public final class Size {
/**
- * Create a new immutable Size instance
+ * Create a new immutable Size instance.
*
- * @param width The width to store in the Size instance
- * @param height The height to store in the Size instance
+ * @param width The width of the size, in pixels
+ * @param height The height of the size, in pixels
*/
- public Size(int width, int height) {
+ public Size(final int width, final int height) {
mWidth = width;
mHeight = height;
}
+ /**
+ * Get the width of the size (in pixels).
+ * @return width
+ */
public final int getWidth() {
return mWidth;
}
+ /**
+ * Get the height of the size (in pixels).
+ * @return height
+ */
public final int getHeight() {
return mHeight;
}
+ /**
+ * Check if this size is equal to another size.
+ * <p>
+ * Two sizes are equal if and only if both their widths and heights are
+ * equal.
+ * </p>
+ * <p>
+ * A size object is never equal to any other type of object.
+ * </p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
@@ -49,27 +72,29 @@
return true;
}
if (obj instanceof Size) {
- Size other = (Size) obj;
+ final Size other = (Size) obj;
return mWidth == other.mWidth && mHeight == other.mHeight;
}
return false;
}
+ /**
+ * Return the size represented as a string with the format {@code "WxH"}
+ *
+ * @return string representation of the size
+ */
@Override
public String toString() {
return mWidth + "x" + mHeight;
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public int hashCode() {
- final long INT_MASK = 0xffffffffL;
-
- long asLong = INT_MASK & mWidth;
- asLong <<= 32;
-
- asLong |= (INT_MASK & mHeight);
-
- return ((Long)asLong).hashCode();
+ // assuming most sizes are <2^16, doing a rotate will give us perfect hashing
+ return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
}
private final int mWidth;
diff --git a/core/java/android/hardware/camera2/StreamConfiguration.java b/core/java/android/hardware/camera2/StreamConfiguration.java
new file mode 100644
index 0000000..c53dd7c
--- /dev/null
+++ b/core/java/android/hardware/camera2/StreamConfiguration.java
@@ -0,0 +1,166 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import static android.hardware.camera2.StreamConfigurationMap.checkArgumentFormatInternal;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.impl.HashCodeHelpers;
+import android.util.Size;
+
+/**
+ * Immutable class to store the available stream
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to be used
+ * when configuring streams with {@link CameraDevice#configureOutputs}.
+ * <!-- TODO: link to input stream configuration -->
+ *
+ * <p>This is the authoritative list for all input/output formats (and sizes respectively
+ * for that format) that are supported by a camera device.</p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ *
+ * @hide
+ */
+public final class StreamConfiguration {
+
+ /**
+ * Create a new {@link StreamConfiguration}.
+ *
+ * @param format image format
+ * @param width image width, in pixels (positive)
+ * @param height image height, in pixels (positive)
+ * @param input true if this is an input configuration, false for output configurations
+ *
+ * @throws IllegalArgumentException
+ * if width/height were not positive
+ * or if the format was not user-defined in ImageFormat/PixelFormat
+ * (IMPL_DEFINED is ok)
+ *
+ * @hide
+ */
+ public StreamConfiguration(
+ final int format, final int width, final int height, final boolean input) {
+ mFormat = checkArgumentFormatInternal(format);
+ mWidth = checkArgumentPositive(width, "width must be positive");
+ mHeight = checkArgumentPositive(width, "height must be positive");
+ mInput = input;
+ }
+
+ /**
+ * Get the image {@code format} in this stream configuration.
+ *
+ * @return an integer format
+ *
+ * @see ImageFormat
+ */
+ public final int getFormat() {
+ return mFormat;
+ }
+
+
+ /**
+ * Return the width of the stream configuration.
+ *
+ * @return width > 0
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Return the height of the stream configuration.
+ *
+ * @return height > 0
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Convenience method to return the size of this stream configuration.
+ *
+ * @return a Size with positive width and height
+ */
+ public Size getSize() {
+ return new Size(mWidth, mHeight);
+ }
+
+ /**
+ * Determines if this configuration is usable for input streams.
+ *
+ * <p>Input and output stream configurations are not interchangeable;
+ * input stream configurations must be used when configuring inputs.</p>
+ *
+ * @return {@code true} if input configuration, {@code false} otherwise
+ */
+ public boolean isInput() {
+ return mInput;
+ }
+
+ /**
+ * Determines if this configuration is usable for output streams.
+ *
+ * <p>Input and output stream configurations are not interchangeable;
+ * out stream configurations must be used when configuring outputs.</p>
+ *
+ * @return {@code true} if output configuration, {@code false} otherwise
+ *
+ * @see CameraDevice#configureOutputs
+ */
+ public boolean isOutput() {
+ return !mInput;
+ }
+
+ /**
+ * Check if this {@link StreamConfiguration} is equal to another {@link StreamConfiguration}.
+ *
+ * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof StreamConfiguration) {
+ final StreamConfiguration other = (StreamConfiguration) obj;
+ return mFormat == other.mFormat &&
+ mWidth == other.mWidth &&
+ mHeight == other.mHeight &&
+ mInput == other.mInput;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight, mInput ? 1 : 0);
+ }
+
+ private final int mFormat;
+ private final int mWidth;
+ private final int mHeight;
+ private final boolean mInput;
+}
diff --git a/core/java/android/hardware/camera2/StreamConfigurationDuration.java b/core/java/android/hardware/camera2/StreamConfigurationDuration.java
new file mode 100644
index 0000000..189ae62
--- /dev/null
+++ b/core/java/android/hardware/camera2/StreamConfigurationDuration.java
@@ -0,0 +1,148 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import static android.hardware.camera2.StreamConfigurationMap.checkArgumentFormatInternal;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.impl.HashCodeHelpers;
+import android.util.Size;
+
+/**
+ * Immutable class to store a time duration for any given format/size combination.
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS
+ *
+ * @hide
+ */
+public final class StreamConfigurationDuration {
+
+ /**
+ * Create a new {@link StreamConfigurationDuration}.
+ *
+ * @param format image format
+ * @param width image width, in pixels (positive)
+ * @param height image height, in pixels (positive)
+ * @param durationNs duration in nanoseconds (non-negative)
+ *
+ * @throws IllegalArgumentException
+ * if width/height were not positive, or durationNs was negative
+ * or if the format was not user-defined in ImageFormat/PixelFormat
+ * (IMPL_DEFINED is OK)
+ *
+ *
+ * @hide
+ */
+ public StreamConfigurationDuration(
+ final int format, final int width, final int height, final long durationNs) {
+ mFormat = checkArgumentFormatInternal(format);
+ mWidth = checkArgumentPositive(width, "width must be positive");
+ mHeight = checkArgumentPositive(width, "height must be positive");
+ mDurationNs = checkArgumentNonnegative(durationNs, "durationNs must be non-negative");
+ }
+
+ /**
+ * Get the image {@code format} in this stream configuration duration
+ *
+ * @return an integer format
+ *
+ * @see ImageFormat
+ */
+ public final int getFormat() {
+ return mFormat;
+ }
+
+
+ /**
+ * Return the width of the stream configuration duration.
+ *
+ * @return width > 0
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Return the height of the stream configuration duration
+ *
+ * @return height > 0
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Convenience method to return the size of this stream configuration duration.
+ *
+ * @return a Size with positive width and height
+ */
+ public Size getSize() {
+ return new Size(mWidth, mHeight);
+ }
+
+ /**
+ * Get the time duration (in nanoseconds).
+ *
+ * @return long >= 0
+ */
+ public long getDuration() {
+ return mDurationNs;
+ }
+
+ /**
+ * Check if this {@link StreamConfigurationDuration} is equal to another
+ * {@link StreamConfigurationDuration}.
+ *
+ * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof StreamConfigurationDuration) {
+ final StreamConfigurationDuration other = (StreamConfigurationDuration) obj;
+ return mFormat == other.mFormat &&
+ mWidth == other.mWidth &&
+ mHeight == other.mHeight &&
+ mDurationNs == other.mDurationNs;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight,
+ (int) mDurationNs, (int)(mDurationNs >>> Integer.SIZE));
+ }
+
+ private final int mFormat;
+ private final int mWidth;
+ private final int mHeight;
+ private final long mDurationNs;
+}
diff --git a/core/java/android/hardware/camera2/StreamConfigurationMap.java b/core/java/android/hardware/camera2/StreamConfigurationMap.java
new file mode 100644
index 0000000..e24fd1b
--- /dev/null
+++ b/core/java/android/hardware/camera2/StreamConfigurationMap.java
@@ -0,0 +1,508 @@
+/*
+ * 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.hardware.camera2;
+
+import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
+import android.hardware.camera2.impl.HashCodeHelpers;
+import android.view.Surface;
+import android.util.Size;
+
+import java.util.Arrays;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Immutable class to store the available stream
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to be used
+ * when configuring streams with {@link CameraDevice#configureOutputs}.
+ * <!-- TODO: link to input stream configuration -->
+ *
+ * <p>This is the authoritative list for all <!-- input/ -->output formats (and sizes respectively
+ * for that format) that are supported by a camera device.</p>
+ *
+ * <p>This also contains the minimum frame durations and stall durations for each format/size
+ * combination that can be used to calculate effective frame rate when submitting multiple captures.
+ * </p>
+ *
+ * <p>An instance of this object is available from {@link CameraCharacteristics} using
+ * the {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS} key and the
+ * {@link CameraCharacteristics#get} method.</p.
+ *
+ * <pre>{@code
+ * CameraCharacteristics characteristics = ...;
+ * StreamConfigurationMap configs = characteristics.get(
+ * CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ * }</pre>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ * @see CameraDevice#configureOutputs
+ */
+public final class StreamConfigurationMap {
+
+ /**
+ * Create a new {@link StreamConfigurationMap}.
+ *
+ * <p>The array parameters ownership is passed to this object after creation; do not
+ * write to them after this constructor is invoked.</p>
+ *
+ * @param configurations a non-{@code null} array of {@link StreamConfiguration}
+ * @param durations a non-{@code null} array of {@link StreamConfigurationDuration}
+ *
+ * @throws NullPointerException if any of the arguments or subelements were {@code null}
+ *
+ * @hide
+ */
+ public StreamConfigurationMap(
+ StreamConfiguration[] configurations,
+ StreamConfigurationDuration[] durations) {
+ // TODO: format check against ImageFormat/PixelFormat ?
+
+ mConfigurations = checkArrayElementsNotNull(configurations, "configurations");
+ mDurations = checkArrayElementsNotNull(durations, "durations");
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the image {@code format} output formats in this stream configuration.
+ *
+ * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
+ * or in {@link PixelFormat} (and there is no possibility of collision).</p>
+ *
+ * <p>Formats listed in this array are guaranteed to return true if queried with
+ * {@link #isOutputSupportedFor(int).</p>
+ *
+ * @return an array of integer format
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public final int[] getOutputFormats() {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the image {@code format} input formats in this stream configuration.
+ *
+ * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
+ * or in {@link PixelFormat} (and there is no possibility of collision).</p>
+ *
+ * @return an array of integer format
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ *
+ * @hide
+ */
+ public final int[] getInputFormats() {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the supported input sizes for this input format.
+ *
+ * <p>The format must have come from {@link #getInputFormats}; otherwise
+ * {@code null} is returned.</p>
+ *
+ * @param format a format from {@link #getInputFormats}
+ * @return a non-empty array of sizes, or {@code null} if the format was not available.
+ *
+ * @hide
+ */
+ public Size[] getInputSizes(final int format) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Determine whether or not output streams can be
+ * {@link CameraDevice#configureOutputs configured} with a particular user-defined format.
+ *
+ * <p>This method determines that the output {@code format} is supported by the camera device;
+ * each output {@code surface} target may or may not itself support that {@code format}.
+ * Refer to the class which provides the surface for additional documentation.</p>
+ *
+ * <p>Formats for which this returns {@code true} are guaranteed to exist in the result
+ * returned by {@link #getOutputSizes}.</p>
+ *
+ * @param format an image format from either {@link ImageFormat} or {@link PixelFormat}
+ * @return
+ * {@code true} iff using a {@code surface} with this {@code format} will be
+ * supported with {@link CameraDevice#configureOutputs}
+ *
+ * @throws IllegalArgumentException
+ * if the image format was not a defined named constant
+ * from either {@link ImageFormat} or {@link PixelFormat}
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ * @see CameraDevice#configureOutputs
+ */
+ public boolean isOutputSupportedFor(int format) {
+ checkArgumentFormat(format);
+
+ final int[] formats = getOutputFormats();
+ for (int i = 0; i < formats.length; ++i) {
+ if (format == formats[i]) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine whether or not output streams can be configured with a particular class
+ * as a consumer.
+ *
+ * <p>The following list is generally usable for outputs:
+ * <ul>
+ * <li>{@link android.media.ImageReader} -
+ * Recommended for image processing or streaming to external resources (such as a file or
+ * network)
+ * <li>{@link android.media.MediaRecorder} -
+ * Recommended for recording video (simple to use)
+ * <li>{@link android.media.MediaCodec} -
+ * Recommended for recording video (more complicated to use, with more flexibility)
+ * <li>{@link android.renderscript.Allocation} -
+ * Recommended for image processing with {@link android.renderscript RenderScript}
+ * <li>{@link android.view.SurfaceHolder} -
+ * Recommended for low-power camera preview with {@link android.view.SurfaceView}
+ * <li>{@link android.graphics.SurfaceTexture} -
+ * Recommended for OpenGL-accelerated preview processing or compositing with
+ * {@link android.view.TextureView}
+ * </ul>
+ * </p>
+ *
+ * <p>Generally speaking this means that creating a {@link Surface} from that class <i>may</i>
+ * provide a producer endpoint that is suitable to be used with
+ * {@link CameraDevice#configureOutputs}.</p>
+ *
+ * <p>Since not all of the above classes support output of all format and size combinations,
+ * the particular combination should be queried with {@link #isOutputSupportedFor(Surface)}.</p>
+ *
+ * @param klass a non-{@code null} {@link Class} object reference
+ * @return {@code true} if this class is supported as an output, {@code false} otherwise
+ *
+ * @throws NullPointerException if {@code klass} was {@code null}
+ *
+ * @see CameraDevice#configureOutputs
+ * @see #isOutputSupportedFor(Surface)
+ */
+ public static <T> boolean isOutputSupportedFor(final Class<T> klass) {
+ checkNotNull(klass, "klass must not be null");
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Determine whether or not the {@code surface} in its current state is suitable to be
+ * {@link CameraDevice#configureOutputs configured} as an output.
+ *
+ * <p>Not all surfaces are usable with the {@link CameraDevice}, and not all configurations
+ * of that {@code surface} are compatible. Some classes that provide the {@code surface} are
+ * compatible with the {@link CameraDevice} in general
+ * (see {@link #isOutputSupportedFor(Class)}, but it is the caller's responsibility to put the
+ * {@code surface} into a state that will be compatible with the {@link CameraDevice}.</p>
+ *
+ * <p>Reasons for a {@code surface} being specifically incompatible might be:
+ * <ul>
+ * <li>Using a format that's not listed by {@link #getOutputFormats}
+ * <li>Using a format/size combination that's not listed by {@link #getOutputSizes}
+ * <li>The {@code surface} itself is not in a state where it can service a new producer.</p>
+ * </li>
+ * </ul>
+ *
+ * This is not an exhaustive list; see the particular class's documentation for further
+ * possible reasons of incompatibility.</p>
+ *
+ * @param surface a non-{@code null} {@link Surface} object reference
+ * @return {@code true} if this is supported, {@code false} otherwise
+ *
+ * @throws NullPointerException if {@code surface} was {@code null}
+ *
+ * @see CameraDevice#configureOutputs
+ * @see #isOutputSupportedFor(Class)
+ */
+ public boolean isOutputSupportedFor(final Surface surface) {
+ checkNotNull(surface, "surface must not be null");
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get a list of sizes compatible with {@code klass} to use as an output.
+ *
+ * <p>Since some of the supported classes may support additional formats beyond
+ * an opaque/implementation-defined (under-the-hood) format; this function only returns
+ * sizes for the implementation-defined format.</p>
+ *
+ * <p>Some classes such as {@link android.media.ImageReader} may only support user-defined
+ * formats; in particular {@link #isOutputSupportedFor(Class)} will return {@code true} for
+ * that class and this method will return an empty array (but not {@code null}).</p>
+ *
+ * <p>If a well-defined format such as {@code NV21} is required, use
+ * {@link #getOutputSizes(int)} instead.</p>
+ *
+ * <p>The {@code klass} should be a supported output, that querying
+ * {@code #isOutputSupportedFor(Class)} should return {@code true}.</p>
+ *
+ * @param klass
+ * a non-{@code null} {@link Class} object reference
+ * @return
+ * an array of supported sizes for implementation-defined formats,
+ * or {@code null} iff the {@code klass} is not a supported output
+ *
+ * @throws NullPointerException if {@code klass} was {@code null}
+ *
+ * @see #isOutputSupportedFor(Class)
+ */
+ public <T> Size[] getOutputSizes(final Class<T> klass) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get a list of sizes compatible with the requested image {@code format}.
+ *
+ * <p>The {@code format} should be a supported format (one of the formats returned by
+ * {@link #getOutputFormats}).</p>
+ *
+ * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+ * @return
+ * an array of supported sizes,
+ * or {@code null} if the {@code format} is not a supported output
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ * @see #getOutputFormats
+ */
+ public Size[] getOutputSizes(final int format) {
+ try {
+ checkArgumentFormatSupported(format, /*output*/true);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+ * for the format/size combination (in nanoseconds).
+ *
+ * <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
+ * <p>{@code size} should be one of the ones returned by
+ * {@link #getOutputSizes(int)}.</p>
+ *
+ * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+ * @param size an output-compatible size
+ * @return a minimum frame duration {@code >=} 0 in nanoseconds
+ *
+ * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} was {@code null}
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public long getOutputMinFrameDuration(final int format, final Size size) {
+ checkArgumentFormatSupported(format, /*output*/true);
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+ * for the class/size combination (in nanoseconds).
+ *
+ * <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
+ * For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
+ *
+ * <p>{@code klass} should be one of the ones which is supported by
+ * {@link #isOutputSupportedFor(Class)}.</p>
+ *
+ * <p>{@code size} should be one of the ones returned by
+ * {@link #getOutputSizes(int)}.</p>
+ *
+ * @param klass
+ * a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
+ * non-empty array returned by {@link #getOutputSizes(Class)}
+ * @param size an output-compatible size
+ * @return a minimum frame duration {@code >=} 0 in nanoseconds
+ *
+ * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public <T> long getOutputMinFrameDuration(final Class<T> klass, final Size size) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the {@link CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS stall duration}
+ * for the format/size combination (in nanoseconds).
+ *
+ * <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
+ * <p>{@code size} should be one of the ones returned by
+ * {@link #getOutputSizes(int)}.</p>
+ *
+ * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+ * @param size an output-compatible size
+ * @return a stall duration {@code >=} 0 in nanoseconds
+ *
+ * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} was {@code null}
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public long getOutputStallDuration(final int format, final Size size) {
+ checkArgumentFormatSupported(format, /*output*/true);
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the {@link CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS stall duration}
+ * for the class/size combination (in nanoseconds).
+ *
+ * <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
+ * For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
+ *
+ * <p>{@code klass} should be one of the ones with a non-empty array returned by
+ * {@link #getOutputSizes(Class)}.</p>
+ *
+ * <p>{@code size} should be one of the ones returned by
+ * {@link #getOutputSizes(Class)}.</p>
+ *
+ * @param klass
+ * a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
+ * non-empty array returned by {@link #getOutputSizes(Class)}
+ * @param size an output-compatible size
+ * @return a minimum frame duration {@code >=} 0 in nanoseconds
+ *
+ * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public <T> long getOutputStallDuration(final Class<T> klass, final Size size) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Check if this {@link StreamConfigurationMap} is equal to another
+ * {@link StreamConfigurationMap}.
+ *
+ * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof StreamConfigurationMap) {
+ final StreamConfigurationMap other = (StreamConfigurationMap) obj;
+ // TODO: do we care about order?
+ return Arrays.equals(mConfigurations, other.mConfigurations) &&
+ Arrays.equals(mDurations, other.mDurations);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // TODO: do we care about order?
+ return HashCodeHelpers.hashCode(mConfigurations) ^ HashCodeHelpers.hashCode(mDurations);
+ }
+
+ // Check that the argument is supported by #getOutputFormats or #getInputFormats
+ private int checkArgumentFormatSupported(int format, boolean output) {
+ checkArgumentFormat(format);
+
+ int[] formats = output ? getOutputFormats() : getInputFormats();
+ for (int i = 0; i < formats.length; ++i) {
+ if (format == formats[i]) {
+ return format;
+ }
+ }
+
+ throw new IllegalArgumentException(String.format(
+ "format %x is not supported by this stream configuration map", format));
+ }
+
+ /**
+ * Ensures that the format is either user-defined or implementation defined.
+ *
+ * <p>Any invalid/undefined formats will raise an exception.</p>
+ *
+ * @param format image format
+ * @return the format
+ *
+ * @throws IllegalArgumentException if the format was invalid
+ */
+ static int checkArgumentFormatInternal(int format) {
+ if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ return format;
+ }
+
+ return checkArgumentFormat(format);
+ }
+
+ /**
+ * Ensures that the format is user-defined in either ImageFormat or PixelFormat.
+ *
+ * <p>Any invalid/undefined formats will raise an exception, including implementation-defined.
+ * </p>
+ *
+ * <p>Note that {@code @hide} and deprecated formats will not pass this check.</p>
+ *
+ * @param format image format
+ * @return the format
+ *
+ * @throws IllegalArgumentException if the format was not user-defined
+ */
+ static int checkArgumentFormat(int format) {
+ if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
+ throw new IllegalArgumentException(String.format(
+ "format %x was not defined in either ImageFormat or PixelFormat", format));
+ }
+
+ return format;
+ }
+
+ private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
+
+ private final StreamConfiguration[] mConfigurations;
+ private final StreamConfigurationDuration[] mDurations;
+
+}
diff --git a/core/java/android/hardware/camera2/TonemapCurve.java b/core/java/android/hardware/camera2/TonemapCurve.java
new file mode 100644
index 0000000..ee20d68
--- /dev/null
+++ b/core/java/android/hardware/camera2/TonemapCurve.java
@@ -0,0 +1,290 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+
+import android.graphics.PointF;
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class for describing a {@code 2 x M x 3} tonemap curve of floats.
+ *
+ * <p>This defines red, green, and blue curves that the {@link CameraDevice} will
+ * use as the tonemapping/contrast/gamma curve when {@link CaptureRequest#TONEMAP_MODE} is
+ * set to {@link CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE}.</p>
+ *
+ * <p>The total number of points {@code (Pin, Pout)} for each color channel can be no more than
+ * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS}.</p>
+ *
+ * <p>The coordinate system for each point is within the inclusive range
+ * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+ *
+ * @see CaptureRequest#TONEMAP_CURVE_BLUE
+ * @see CaptureRequest#TONEMAP_CURVE_GREEN
+ * @see CaptureRequest#TONEMAP_CURVE_RED
+ * @see CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE
+ * @see CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS
+ */
+public final class TonemapCurve {
+ /**
+ * Lower bound tonemap value corresponding to pure black for a single color channel.
+ */
+ public static final float LEVEL_BLACK = 0.0f;
+
+ /**
+ * Upper bound tonemap value corresponding to a pure white for a single color channel.
+ */
+ public static final float LEVEL_WHITE = 1.0f;
+
+ /**
+ * Number of elements in a {@code (Pin, Pout)} point;
+ */
+ public static final int POINT_SIZE = 2;
+
+ /**
+ * Index of the red color channel curve.
+ */
+ public static final int CHANNEL_RED = 0;
+ /**
+ * Index of the green color channel curve.
+ */
+ public static final int CHANNEL_GREEN = 1;
+ /**
+ * Index of the blue color channel curve.
+ */
+ public static final int CHANNEL_BLUE = 2;
+
+ /**
+ * Create a new immutable TonemapCurve instance.
+ *
+ * <p>Values are stored as a contiguous {@code (Pin, Pout}) point.</p>
+ *
+ * <p>All parameters may have independent length but should have at most
+ * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS} * {@value #POINT_SIZE} elements.</p>
+ *
+ * <p>All sub-elements must be in the inclusive range of
+ * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+ *
+ * <p>This constructor copies the array contents and does not retain ownership of the array.</p>
+ *
+ * @param elements An array of elements whose length is {@code CHANNEL_COUNT * rows * columns}
+ *
+ * @throws IllegalArgumentException
+ * if the {@code elements} array length is invalid,
+ * if any of the subelems are not finite
+ * @throws NullPointerException
+ * if any of the parameters is {@code null}
+ *
+ * @hide
+ */
+ public TonemapCurve(float[] red, float[] green, float[] blue) {
+ // TODO: maxCurvePoints check?
+
+ checkNotNull(red, "red must not be null");
+ checkNotNull(green, "green must not be null");
+ checkNotNull(blue, "blue must not be null");
+
+ checkArgumentArrayLengthDivisibleBy(red, POINT_SIZE, "red");
+ checkArgumentArrayLengthDivisibleBy(green, POINT_SIZE, "green");
+ checkArgumentArrayLengthDivisibleBy(blue, POINT_SIZE, "blue");
+
+ checkArrayElementsInRange(red, LEVEL_BLACK, LEVEL_WHITE, "red");
+ checkArrayElementsInRange(green, LEVEL_BLACK, LEVEL_WHITE, "green");
+ checkArrayElementsInRange(blue, LEVEL_BLACK, LEVEL_WHITE, "blue");
+
+ mRed = Arrays.copyOf(red, red.length);
+ mGreen = Arrays.copyOf(green, green.length);
+ mBlue = Arrays.copyOf(blue, blue.length);
+ }
+
+ private static void checkArgumentArrayLengthDivisibleBy(float[] array,
+ int divisible, String arrayName) {
+ if (array.length % divisible != 0) {
+ throw new IllegalArgumentException(arrayName + " size must be divisible by "
+ + divisible);
+ }
+ }
+
+ private static int checkArgumentColorChannel(int colorChannel) {
+ switch (colorChannel) {
+ case CHANNEL_RED:
+ case CHANNEL_GREEN:
+ case CHANNEL_BLUE:
+ break;
+ default:
+ throw new IllegalArgumentException("colorChannel out of range");
+ }
+
+ return colorChannel;
+ }
+
+ /**
+ * Get the number of points stored in this tonemap curve for the specified color channel.
+ *
+ * @param colorChannel one of {@link #CHANNEL_RED}, {@link #CHANNEL_GREEN}, {@link #CHANNEL_BLUE}
+ * @return number of points stored in this tonemap for that color's curve (>= 0)
+ *
+ * @throws IllegalArgumentException if {@code colorChannel} was out of range
+ */
+ public int getPointCount(int colorChannel) {
+ checkArgumentColorChannel(colorChannel);
+
+ return getCurve(colorChannel).length / POINT_SIZE;
+ }
+
+ /**
+ * Get the point for a color channel at a specified index.
+ *
+ * <p>The index must be at least 0 but no greater than {@link #getPointCount(int)} for
+ * that {@code colorChannel}.</p>
+ *
+ * <p>All returned coordinates in the point are between the range of
+ * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+ *
+ * @param colorChannel {@link #CHANNEL_RED}, {@link #CHANNEL_GREEN}, or {@link #CHANNEL_BLUE}
+ * @param index at least 0 but no greater than {@code getPointCount(colorChannel)}
+ * @return the {@code (Pin, Pout)} pair mapping the tone for that index
+ *
+ * @throws IllegalArgumentException if {@code colorChannel} or {@code index} was out of range
+ *
+ * @see #LEVEL_BLACK
+ * @see #LEVEL_WHITE
+ */
+ public PointF getPoint(int colorChannel, int index) {
+ checkArgumentColorChannel(colorChannel);
+ if (index < 0 || index >= getPointCount(colorChannel)) {
+ throw new IllegalArgumentException("index out of range");
+ }
+
+ final float[] curve = getCurve(colorChannel);
+
+ final float pIn = curve[index * POINT_SIZE + OFFSET_POINT_IN];
+ final float pOut = curve[index * POINT_SIZE + OFFSET_POINT_OUT];
+
+ return new PointF(pIn, pOut);
+ }
+
+ /**
+ * Copy the color curve for a single color channel from this tonemap curve into the destination.
+ *
+ * <p>
+ * <!--The output is encoded the same as in the constructor -->
+ * Values are stored as packed {@code (Pin, Pout}) points, and there are a total of
+ * {@link #getPointCount} points for that respective channel.</p>
+ *
+ * <p>All returned coordinates are between the range of
+ * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+ *
+ * @param destination
+ * an array big enough to hold at least {@link #getPointCount} {@code *}
+ * {@link #POINT_SIZE} elements after the {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws IllegalArgumentException
+ * If offset was negative
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ *
+ * @see CaptureRequest#TONEMAP_CURVE_BLUE
+ * @see CaptureRequest#TONEMAP_CURVE_RED
+ * @see CaptureRequest#TONEMAP_CURVE_GREEN
+ * @see #LEVEL_BLACK
+ * @see #LEVEL_WHITE
+ */
+ public void copyColorCurve(int colorChannel, float[] destination,
+ int offset) {
+ checkArgumentNonnegative(offset, "offset must not be negative");
+ checkNotNull(destination, "destination must not be null");
+
+ if (destination.length + offset < getPointCount(colorChannel) * POINT_SIZE) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ float[] curve = getCurve(colorChannel);
+ System.arraycopy(curve, /*srcPos*/0, destination, offset, curve.length);
+ }
+
+ /**
+ * Check if this TonemapCurve is equal to another TonemapCurve.
+ *
+ * <p>Two matrices are equal if and only if all of their elements are
+ * {@link Object#equals equal}.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof TonemapCurve) {
+ final TonemapCurve other = (TonemapCurve) obj;
+ return Arrays.equals(mRed, other.mRed) &&
+ Arrays.equals(mGreen, other.mGreen) &&
+ Arrays.equals(mBlue, other.mBlue);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ if (mHashCalculated) {
+ // Avoid re-calculating hash. Data is immutable so this is both legal and faster.
+ return mHashCode;
+ }
+
+ mHashCode = HashCodeHelpers.hashCode(mRed, mGreen, mBlue);
+ mHashCalculated = true;
+
+ return mHashCode;
+ }
+
+ private float[] getCurve(int colorChannel) {
+ switch (colorChannel) {
+ case CHANNEL_RED:
+ return mRed;
+ case CHANNEL_GREEN:
+ return mGreen;
+ case CHANNEL_BLUE:
+ return mBlue;
+ default:
+ throw new AssertionError("colorChannel out of range");
+ }
+ }
+
+ private final static int OFFSET_POINT_IN = 0;
+ private final static int OFFSET_POINT_OUT = 1;
+
+ private final float[] mRed;
+ private final float[] mGreen;
+ private final float[] mBlue;
+
+ private int mHashCode;
+ private boolean mHashCalculated = false;
+};
diff --git a/core/java/android/hardware/camera2/impl/HashCodeHelpers.java b/core/java/android/hardware/camera2/impl/HashCodeHelpers.java
new file mode 100644
index 0000000..2d63827
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/HashCodeHelpers.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.impl;
+
+/**
+ * Provide hashing functions using the Modified Bernstein hash
+ */
+public final class HashCodeHelpers {
+
+ /**
+ * Hash every element uniformly using the Modified Bernstein hash.
+ *
+ * <p>Useful to implement a {@link Object#hashCode} for uniformly distributed data.</p>
+ *
+ * @param array a non-{@code null} array of integers
+ *
+ * @return the numeric hash code
+ */
+ public static int hashCode(int[] array) {
+ if (array == null) {
+ return 0;
+ }
+
+ /*
+ * Note that we use 31 here instead of 33 since it's preferred in Effective Java
+ * and used elsewhere in the runtime (e.g. Arrays#hashCode)
+ *
+ * That being said 33 and 31 are nearly identical in terms of their usefulness
+ * according to http://svn.apache.org/repos/asf/apr/apr/trunk/tables/apr_hash.c
+ */
+ int h = 1;
+ for (int x : array) {
+ // Strength reduction; in case the compiler has illusions about divisions being faster
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+ }
+
+ return h;
+ }
+
+ /**
+ * Hash every element uniformly using the Modified Bernstein hash.
+ *
+ * <p>Useful to implement a {@link Object#hashCode} for uniformly distributed data.</p>
+ *
+ * @param array a non-{@code null} array of floats
+ *
+ * @return the numeric hash code
+ */
+ public static int hashCode(float[] array) {
+ if (array == null) {
+ return 0;
+ }
+
+ int h = 1;
+ for (float f : array) {
+ int x = Float.floatToIntBits(f);
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+ }
+
+ return h;
+ }
+
+ /**
+ * Hash every element uniformly using the Modified Bernstein hash.
+ *
+ * <p>Useful to implement a {@link Object#hashCode} for uniformly distributed data.</p>
+ *
+ * @param array a non-{@code null} array of objects
+ *
+ * @return the numeric hash code
+ */
+ public static <T> int hashCode(T[] array) {
+ if (array == null) {
+ return 0;
+ }
+
+ int h = 1;
+ for (T o : array) {
+ int x = (o == null) ? 0 : o.hashCode();
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+ }
+
+ return h;
+ }
+
+ public static <T> int hashCode(T a) {
+ return (a == null) ? 0 : a.hashCode();
+ }
+
+ public static <T> int hashCode(T a, T b) {
+ int h = hashCode(a);
+
+ int x = (b == null) ? 0 : b.hashCode();
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+
+ return h;
+ }
+
+ public static <T> int hashCode(T a, T b, T c) {
+ int h = hashCode(a, b);
+
+ int x = (a == null) ? 0 : a.hashCode();
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+
+ return h;
+ }
+
+ public static int hashCode(int x) {
+ return hashCode(new int[] { x } );
+ }
+
+ public static int hashCode(int x, int y) {
+ return hashCode(new int[] { x, y } );
+ }
+
+ public static int hashCode(int x, int y, int z) {
+ return hashCode(new int[] { x, y, z } );
+ }
+
+ public static int hashCode(int x, int y, int z, int w) {
+ return hashCode(new int[] { x, y, z, w } );
+ }
+
+ public static int hashCode(int x, int y, int z, int w, int t) {
+ return hashCode(new int[] { x, y, z, w, t } );
+ }
+
+
+}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9e9820f..f1ad1f8 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -175,6 +175,8 @@
private static final String POWER_USE_ITEM_DATA = "pwi";
private static final String DISCHARGE_STEP_DATA = "dsd";
private static final String CHARGE_STEP_DATA = "csd";
+ private static final String DISCHARGE_TIME_REMAIN_DATA = "dtr";
+ private static final String CHARGE_TIME_REMAIN_DATA = "ctr";
private final StringBuilder mFormatBuilder = new StringBuilder(32);
private final Formatter mFormatter = new Formatter(mFormatBuilder);
@@ -3076,7 +3078,7 @@
HISTORY_STATE2_DESCRIPTIONS, !checkin);
if (rec.wakeReasonTag != null) {
if (checkin) {
- pw.print(",Wr=");
+ pw.print(",wr=");
pw.print(rec.wakeReasonTag.poolIdx);
} else {
pw.print(" wake_reason=");
@@ -3423,8 +3425,21 @@
if (!filtering) {
dumpDurationSteps(pw, DISCHARGE_STEP_DATA, getDischargeStepDurationsArray(),
getNumDischargeStepDurations(), true);
+ String[] lineArgs = new String[1];
+ long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
+ if (timeRemaining >= 0) {
+ lineArgs[0] = Long.toString(timeRemaining);
+ dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
+ (Object[])lineArgs);
+ }
dumpDurationSteps(pw, CHARGE_STEP_DATA, getChargeStepDurationsArray(),
getNumChargeStepDurations(), true);
+ timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
+ if (timeRemaining >= 0) {
+ lineArgs[0] = Long.toString(timeRemaining);
+ dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
+ (Object[])lineArgs);
+ }
}
if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
diff --git a/core/java/android/util/Range.java b/core/java/android/util/Range.java
new file mode 100644
index 0000000..9a4bd4b
--- /dev/null
+++ b/core/java/android/util/Range.java
@@ -0,0 +1,144 @@
+/*
+ * 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.util;
+
+import static com.android.internal.util.Preconditions.*;
+
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+/**
+ * Immutable class for describing the range of two numeric values.
+ * <p>
+ * A range (or "interval") defines the inclusive boundaries around a contiguous span of
+ * values of some {@link Comparable} type; for example,
+ * "integers from 1 to 100 inclusive."
+ * </p>
+ * <p>
+ * All ranges are bounded, and the left side of the range is always {@code >=}
+ * the right side of the range.
+ * </p>
+ *
+ * <p>Although the implementation itself is immutable, there is no restriction that objects
+ * stored must also be immutable. If mutable objects are stored here, then the range
+ * effectively becomes mutable. </p>
+ */
+public final class Range<T extends Comparable<? super T>> {
+ /**
+ * Create a new immutable range.
+ *
+ * <p>
+ * The endpoints are {@code [lower, upper]}; that
+ * is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal}
+ * to {@code upper}.
+ * </p>
+ *
+ * @param lower The lower endpoint (inclusive)
+ * @param upper The upper endpoint (inclusive)
+ *
+ * @throws NullPointerException if {@code lower} or {@code upper} is {@code null}
+ */
+ public Range(final T lower, final T upper) {
+ mLower = checkNotNull(lower, "lower must not be null");
+ mUpper = checkNotNull(upper, "upper must not be null");
+
+ if (lower.compareTo(upper) > 0) {
+ throw new IllegalArgumentException("lower must be less than or equal to upper");
+ }
+ }
+
+ /**
+ * Create a new immutable range, with the argument types inferred.
+ *
+ * <p>
+ * The endpoints are {@code [lower, upper]}; that
+ * is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal}
+ * to {@code upper}.
+ * </p>
+ *
+ * @param lower The lower endpoint (inclusive)
+ * @param upper The upper endpoint (inclusive)
+ *
+ * @throws NullPointerException if {@code lower} or {@code upper} is {@code null}
+ */
+ public static <T extends Comparable<? super T>> Range<T> create(final T lower, final T upper) {
+ return new Range<T>(lower, upper);
+ }
+
+ /**
+ * Get the lower endpoint.
+ *
+ * @return a non-{@code null} {@code T} reference
+ */
+ public T getLower() {
+ return mLower;
+ }
+
+ /**
+ * Get the upper endpoint.
+ *
+ * @return a non-{@code null} {@code T} reference
+ */
+ public T getUpper() {
+ return mUpper;
+ }
+
+ /**
+ * Compare two ranges for equality.
+ *
+ * <p>A range is considered equal if and only if both the lower and upper endpoints
+ * are also equal.</p>
+ *
+ * @return {@code true} if the ranges are equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Range) {
+ @SuppressWarnings("rawtypes")
+ final
+ Range other = (Range) obj;
+ return mLower.equals(other.mLower) && mUpper.equals(other.mUpper);
+ }
+ return false;
+ }
+
+ /**
+ * Return the range as a string representation {@code "[lower, upper]"}.
+ *
+ * @return string representation of the range
+ */
+ @Override
+ public String toString() {
+ return String.format("[%s, %s]", mLower, mUpper);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mLower, mUpper);
+ }
+
+ private final T mLower;
+ private final T mUpper;
+};
diff --git a/core/java/android/util/Size.java b/core/java/android/util/Size.java
new file mode 100644
index 0000000..ba1a35f
--- /dev/null
+++ b/core/java/android/util/Size.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+/**
+ * Immutable class for describing width and height dimensions in pixels.
+ */
+public final class Size {
+ /**
+ * Create a new immutable Size instance.
+ *
+ * @param width The width of the size, in pixels
+ * @param height The height of the size, in pixels
+ */
+ public Size(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ /**
+ * Get the width of the size (in pixels).
+ * @return width
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Get the height of the size (in pixels).
+ * @return height
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Check if this size is equal to another size.
+ * <p>
+ * Two sizes are equal if and only if both their widths and heights are
+ * equal.
+ * </p>
+ * <p>
+ * A size object is never equal to any other type of object.
+ * </p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Size) {
+ Size other = (Size) obj;
+ return mWidth == other.mWidth && mHeight == other.mHeight;
+ }
+ return false;
+ }
+
+ /**
+ * Return the size represented as a string with the format {@code "WxH"}
+ *
+ * @return string representation of the size
+ */
+ @Override
+ public String toString() {
+ return mWidth + "x" + mHeight;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // assuming most sizes are <2^16, doing a rotate will give us perfect hashing
+ return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
+ }
+
+ private final int mWidth;
+ private final int mHeight;
+};
diff --git a/core/java/android/util/SizeF.java b/core/java/android/util/SizeF.java
new file mode 100644
index 0000000..0a8b4ed
--- /dev/null
+++ b/core/java/android/util/SizeF.java
@@ -0,0 +1,108 @@
+/*
+ * 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.util;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Immutable class for describing width and height dimensions in some arbitrary
+ * unit.
+ * <p>
+ * Width and height are finite values stored as a floating point representation.
+ * </p>
+ */
+public final class SizeF {
+ /**
+ * Create a new immutable SizeF instance.
+ *
+ * <p>Both the {@code width} and the {@code height} must be a finite number.
+ * In particular, {@code NaN} and positive/negative infinity are illegal values.</p>
+ *
+ * @param width The width of the size
+ * @param height The height of the size
+ *
+ * @throws IllegalArgumentException
+ * if either {@code width} or {@code height} was not finite.
+ */
+ public SizeF(final float width, final float height) {
+ mWidth = checkArgumentFinite(width, "width");
+ mHeight = checkArgumentFinite(height, "height");
+ }
+
+ /**
+ * Get the width of the size (as an arbitrary unit).
+ * @return width
+ */
+ public float getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Get the height of the size (as an arbitrary unit).
+ * @return height
+ */
+ public float getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Check if this size is equal to another size.
+ *
+ * <p>Two sizes are equal if and only if both their widths and heights are the same.</p>
+ *
+ * <p>For this purpose, the width/height float values are considered to be the same if and only
+ * if the method {@link Float#floatToIntBits(float)} returns the identical {@code int} value
+ * when applied to each.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof SizeF) {
+ final SizeF other = (SizeF) obj;
+ return mWidth == other.mWidth && mHeight == other.mHeight;
+ }
+ return false;
+ }
+
+ /**
+ * Return the size represented as a string with the format {@code "WxH"}
+ *
+ * @return string representation of the size
+ */
+ @Override
+ public String toString() {
+ return mWidth + "x" + mHeight;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Float.floatToIntBits(mWidth) ^ Float.floatToIntBits(mHeight);
+ }
+
+ private final float mWidth;
+ private final float mHeight;
+};
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 34b85d9..11948b2 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -18,6 +18,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
import android.graphics.DrawFilter;
import android.graphics.Matrix;
import android.graphics.NinePatch;
@@ -889,6 +890,16 @@
float radius, long paint);
@Override
+ public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
+ CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
+ nDrawCircle(mRenderer, cx.getNativeContainer(), cy.getNativeContainer(),
+ radius.getNativeContainer(), paint.getNativeContainer());
+ }
+
+ private static native void nDrawCircle(long renderer, long propCx,
+ long propCy, long propRadius, long propPaint);
+
+ @Override
public void drawColor(int color) {
drawColor(color, PorterDuff.Mode.SRC_OVER);
}
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index 2b29e5c..a94ec3a 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.NonNull;
import android.util.Pools.SynchronizedPool;
/**
@@ -32,19 +33,25 @@
private static final SynchronizedPool<GLES20RecordingCanvas> sPool =
new SynchronizedPool<GLES20RecordingCanvas>(POOL_LIMIT);
+ RenderNode mNode;
+
private GLES20RecordingCanvas() {
super(true, true);
}
- static GLES20RecordingCanvas obtain() {
+ static GLES20RecordingCanvas obtain(@NonNull RenderNode node) {
+ if (node == null) throw new IllegalArgumentException("node cannot be null");
+
GLES20RecordingCanvas canvas = sPool.acquire();
if (canvas == null) {
canvas = new GLES20RecordingCanvas();
}
+ canvas.mNode = node;
return canvas;
}
void recycle() {
+ mNode = null;
sPool.release(this);
}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 233f846..7ec2cc6 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -18,6 +18,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -189,4 +190,7 @@
* @hide
*/
abstract void clearLayerUpdates();
+
+ public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
+ CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
}
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 8b80c3e0..0cfde94 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -239,7 +239,7 @@
* @see #isValid()
*/
public HardwareCanvas start(int width, int height) {
- HardwareCanvas canvas = GLES20RecordingCanvas.obtain();
+ HardwareCanvas canvas = GLES20RecordingCanvas.obtain(this);
canvas.setViewport(width, height);
// The dirty rect should always be null for a display list
canvas.onPreDraw(null);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index b70ae3d..a675821 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -16,6 +16,9 @@
package android.view;
+import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
import android.util.SparseIntArray;
import java.lang.ref.WeakReference;
@@ -26,18 +29,22 @@
public final class RenderNodeAnimator {
// Keep in sync with enum RenderProperty in Animator.h
- private static final int TRANSLATION_X = 0;
- private static final int TRANSLATION_Y = 1;
- private static final int TRANSLATION_Z = 2;
- private static final int SCALE_X = 3;
- private static final int SCALE_Y = 4;
- private static final int ROTATION = 5;
- private static final int ROTATION_X = 6;
- private static final int ROTATION_Y = 7;
- private static final int X = 8;
- private static final int Y = 9;
- private static final int Z = 10;
- private static final int ALPHA = 11;
+ public static final int TRANSLATION_X = 0;
+ public static final int TRANSLATION_Y = 1;
+ public static final int TRANSLATION_Z = 2;
+ public static final int SCALE_X = 3;
+ public static final int SCALE_Y = 4;
+ public static final int ROTATION = 5;
+ public static final int ROTATION_X = 6;
+ public static final int ROTATION_Y = 7;
+ public static final int X = 8;
+ public static final int Y = 9;
+ public static final int Z = 10;
+ public static final int ALPHA = 11;
+
+ // Keep in sync with enum PaintFields in Animator.h
+ public static final int PAINT_STROKE_WIDTH = 0;
+ public static final int PAINT_ALPHA = 1;
// ViewPropertyAnimator uses a mask for its values, we need to remap them
// to the enum values here. RenderPropertyAnimator can't use the mask values
@@ -59,8 +66,8 @@
}};
// Keep in sync DeltaValueType in Animator.h
- private static final int DELTA_TYPE_ABSOLUTE = 0;
- private static final int DELTA_TYPE_DELTA = 1;
+ public static final int DELTA_TYPE_ABSOLUTE = 0;
+ public static final int DELTA_TYPE_DELTA = 1;
private RenderNode mTarget;
private long mNativePtr;
@@ -74,6 +81,19 @@
property, deltaType, deltaValue);
}
+ public RenderNodeAnimator(CanvasProperty<Float> property, int deltaType, float deltaValue) {
+ mNativePtr = nCreateCanvasPropertyFloatAnimator(
+ new WeakReference<RenderNodeAnimator>(this),
+ property.getNativeContainer(), deltaType, deltaValue);
+ }
+
+ public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField,
+ int deltaType, float deltaValue) {
+ mNativePtr = nCreateCanvasPropertyPaintAnimator(
+ new WeakReference<RenderNodeAnimator>(this),
+ property.getNativeContainer(), paintField, deltaType, deltaValue);
+ }
+
public void start(View target) {
mTarget = target.mRenderNode;
mTarget.addAnimator(this);
@@ -81,6 +101,15 @@
target.invalidateViewProperty(true, false);
}
+ public void start(Canvas canvas) {
+ if (!(canvas instanceof GLES20RecordingCanvas)) {
+ throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
+ }
+ GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
+ mTarget = recordingCanvas.mNode;
+ mTarget.addAnimator(this);
+ }
+
public void cancel() {
mTarget.removeAnimator(this);
}
@@ -117,6 +146,10 @@
private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
int property, int deltaValueType, float deltaValue);
+ private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
+ long canvasProperty, int deltaValueType, float deltaValue);
+ private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
+ long canvasProperty, int paintField, int deltaValueType, float deltaValue);
private static native void nSetDuration(long nativePtr, int duration);
private static native void nUnref(long nativePtr);
}
diff --git a/core/java/android/webkit/ClientCertRequest.java b/core/java/android/webkit/ClientCertRequest.java
index 8951786..588b868 100644
--- a/core/java/android/webkit/ClientCertRequest.java
+++ b/core/java/android/webkit/ClientCertRequest.java
@@ -36,8 +36,6 @@
* host/port pair. The user can clear the cached data using
* {@link WebView#clearClientCertPreferences}.
*
- * TODO(sgurun) unhide
- * @hide
*/
public interface ClientCertRequest {
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index efb246a..d06cd75 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -33,6 +33,7 @@
import android.os.Message;
import android.os.StrictMode;
import android.print.PrintDocumentAdapter;
+import android.security.KeyChain;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
@@ -1479,18 +1480,16 @@
* Clears the client certificate preferences table stored in response
* to proceeding/cancelling client cert requests. Note that webview
* automatically clears these preferences when it receives a
- * {@link KeyChain.ACTION_STORAGE_CHANGED}
+ * {@link KeyChain#ACTION_STORAGE_CHANGED} intent. The client certificate
+ * preferences are global for all Webviews.
*
- * @param resultCallback A callback to be invoked when client certs are cleared.
- * The embedder can pass null if not interested in the callback.
- *
- * TODO(sgurun) unhide
- * @hide
+ * @param onCleared A runnable to be invoked when client certs are cleared.
+ * The embedder can pass null if not interested in the
+ * callback. The runnable will be called in UI thread.
*/
- public void clearClientCertPreferences(ValueCallback<Void> resultCallback) {
- checkThread();
+ public static void clearClientCertPreferences(Runnable onCleared) {
if (DebugFlags.TRACE_API) Log.d(LOGTAG, "clearClientCertPreferences");
- mProvider.clearClientCertPreferences(resultCallback);
+ getFactory().getStatics().clearClientCertPreferences(onCleared);
}
/**
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 107ae4f..62b80c4a 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -224,8 +224,6 @@
* @param view The WebView that is initiating the callback
* @param request An instance of a {@link ClientCertRequest}
*
- * TODO(sgurun) unhide
- * @hide
*/
public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
request.cancel();
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index e391aaf..945e0e3 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -59,6 +59,13 @@
* {@link android.webkit.WebView#setWebContentsDebuggingEnabled(boolean) }
*/
void setWebContentsDebuggingEnabled(boolean enable);
+
+ /**
+ * Implements the API method:
+ * {@link android.webkit.WebView#clearClientCertPreferences(Runnable) }
+ */
+ void clearClientCertPreferences(Runnable onCleared);
+
}
Statics getStatics();
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index efa5497..5081ff5 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -198,8 +198,6 @@
public void clearSslPreferences();
- public void clearClientCertPreferences(ValueCallback<Void> resultCallback);
-
public WebBackForwardList copyBackForwardList();
public void setFindListener(WebView.FindListener listener);
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index a54b364..f6722a6 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -30,7 +30,7 @@
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
- public static <T> T checkNotNull(T reference) {
+ public static <T> T checkNotNull(final T reference) {
if (reference == null) {
throw new NullPointerException();
}
@@ -47,7 +47,7 @@
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
- public static <T> T checkNotNull(T reference, Object errorMessage) {
+ public static <T> T checkNotNull(final T reference, final Object errorMessage) {
if (reference == null) {
throw new NullPointerException(String.valueOf(errorMessage));
}
@@ -61,7 +61,7 @@
* @param expression a boolean expression
* @throws IllegalStateException if {@code expression} is false
*/
- public static void checkState(boolean expression) {
+ public static void checkState(final boolean expression) {
if (!expression) {
throw new IllegalStateException();
}
@@ -71,11 +71,178 @@
* Check the requested flags, throwing if any requested flags are outside
* the allowed set.
*/
- public static void checkFlagsArgument(int requestedFlags, int allowedFlags) {
+ public static void checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
if ((requestedFlags & allowedFlags) != requestedFlags) {
throw new IllegalArgumentException("Requested flags 0x"
+ Integer.toHexString(requestedFlags) + ", but only 0x"
+ Integer.toHexString(allowedFlags) + " are allowed");
}
}
+
+ /**
+ * Ensures that that the argument numeric value is non-negative.
+ *
+ * @param value a numeric int value
+ * @param errorMessage the exception message to use if the check fails
+ * @return the validated numeric value
+ * @throws IllegalArgumentException if {@code value} was negative
+ */
+ public static int checkArgumentNonnegative(final int value, final String errorMessage) {
+ if (value < 0) {
+ throw new IllegalArgumentException(errorMessage);
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that that the argument numeric value is non-negative.
+ *
+ * @param value a numeric long value
+ * @param errorMessage the exception message to use if the check fails
+ * @return the validated numeric value
+ * @throws IllegalArgumentException if {@code value} was negative
+ */
+ public static long checkArgumentNonnegative(final long value, final String errorMessage) {
+ if (value < 0) {
+ throw new IllegalArgumentException(errorMessage);
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that that the argument numeric value is positive.
+ *
+ * @param value a numeric int value
+ * @param errorMessage the exception message to use if the check fails
+ * @return the validated numeric value
+ * @throws IllegalArgumentException if {@code value} was not positive
+ */
+ public static int checkArgumentPositive(final int value, final String errorMessage) {
+ if (value <= 0) {
+ throw new IllegalArgumentException(errorMessage);
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that the argument floating point value is a finite number.
+ *
+ * <p>A finite number is defined to be both representable (that is, not NaN) and
+ * not infinite (that is neither positive or negative infinity).</p>
+ *
+ * @param value a floating point value
+ * @param valueName the name of the argument to use if the check fails
+ *
+ * @return the validated floating point value
+ *
+ * @throws IllegalArgumentException if {@code value} was not finite
+ */
+ public static float checkArgumentFinite(final float value, final String valueName) {
+ if (Float.isNaN(value)) {
+ throw new IllegalArgumentException(valueName + " must not be NaN");
+ } else if (Float.isInfinite(value)) {
+ throw new IllegalArgumentException(valueName + " must not be infinite");
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that the argument floating point value is within the inclusive range.
+ *
+ * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
+ * will always be out of range.</p>
+ *
+ * @param value a floating point value
+ * @param lower the lower endpoint of the inclusive range
+ * @param upper the upper endpoint of the inclusive range
+ * @param valueName the name of the argument to use if the check fails
+ *
+ * @return the validated floating point value
+ *
+ * @throws IllegalArgumentException if {@code value} was not within the range
+ */
+ public static float checkArgumentInRange(float value, float lower, float upper,
+ String valueName) {
+ if (Float.isNaN(value)) {
+ throw new IllegalArgumentException(valueName + " must not be NaN");
+ } else if (value < lower) {
+ throw new IllegalArgumentException(
+ String.format(
+ "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
+ } else if (value > upper) {
+ throw new IllegalArgumentException(
+ String.format(
+ "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that the array is not {@code null}, and none if its elements are {@code null}.
+ *
+ * @param value an array of boxed objects
+ * @param valueName the name of the argument to use if the check fails
+ *
+ * @return the validated array
+ *
+ * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
+ */
+ public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
+ if (value == null) {
+ throw new NullPointerException(valueName + " must not be null");
+ }
+
+ for (int i = 0; i < value.length; ++i) {
+ if (value[i] == null) {
+ throw new NullPointerException(
+ String.format("%s[%d] must not be null", valueName, i));
+ }
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that all elements in the argument floating point array are within the inclusive range
+ *
+ * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
+ * will always be out of range.</p>
+ *
+ * @param value a floating point array of values
+ * @param lower the lower endpoint of the inclusive range
+ * @param upper the upper endpoint of the inclusive range
+ * @param valueName the name of the argument to use if the check fails
+ *
+ * @return the validated floating point value
+ *
+ * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
+ * @throws NullPointerException if the {@code value} was {@code null}
+ */
+ public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
+ String valueName) {
+ checkNotNull(value, valueName + " must not be null");
+
+ for (int i = 0; i < value.length; ++i) {
+ float v = value[i];
+
+ if (Float.isNaN(v)) {
+ throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
+ } else if (v < lower) {
+ throw new IllegalArgumentException(
+ String.format("%s[%d] is out of range of [%f, %f] (too low)",
+ valueName, i, lower, upper));
+ } else if (v > upper) {
+ throw new IllegalArgumentException(
+ String.format("%s[%d] is out of range of [%f, %f] (too high)",
+ valueName, i, lower, upper));
+ }
+ }
+
+ return value;
+ }
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index ee59c8a..667bf6c 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -92,6 +92,7 @@
android/graphics/BitmapFactory.cpp \
android/graphics/Camera.cpp \
android/graphics/Canvas.cpp \
+ android/graphics/CanvasProperty.cpp \
android/graphics/ColorFilter.cpp \
android/graphics/DrawFilter.cpp \
android/graphics/CreateJavaOutputStreamAdaptor.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f964cd2..66fbb8e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -105,6 +105,7 @@
extern int register_android_content_XmlBlock(JNIEnv* env);
extern int register_android_emoji_EmojiFactory(JNIEnv* env);
extern int register_android_graphics_Canvas(JNIEnv* env);
+extern int register_android_graphics_CanvasProperty(JNIEnv* env);
extern int register_android_graphics_ColorFilter(JNIEnv* env);
extern int register_android_graphics_DrawFilter(JNIEnv* env);
extern int register_android_graphics_Matrix(JNIEnv* env);
@@ -1221,6 +1222,7 @@
REG_JNI(register_android_graphics_Camera),
REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor),
REG_JNI(register_android_graphics_Canvas),
+ REG_JNI(register_android_graphics_CanvasProperty),
REG_JNI(register_android_graphics_ColorFilter),
REG_JNI(register_android_graphics_DrawFilter),
REG_JNI(register_android_graphics_Interpolator),
diff --git a/core/jni/android/graphics/CanvasProperty.cpp b/core/jni/android/graphics/CanvasProperty.cpp
new file mode 100644
index 0000000..70e2db5
--- /dev/null
+++ b/core/jni/android/graphics/CanvasProperty.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 20014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/VirtualLightRefBase.h>
+#include <CanvasProperty.h>
+
+namespace android {
+
+using namespace uirenderer;
+
+#ifdef USE_OPENGL_RENDERER
+
+static jlong incRef(VirtualLightRefBase* ptr) {
+ ptr->incStrong(0);
+ return reinterpret_cast<jlong>(ptr);
+}
+
+static jlong createFloat(JNIEnv* env, jobject clazz, jfloat initialValue) {
+ return incRef(new CanvasPropertyPrimitive(initialValue));
+}
+
+static jlong createPaint(JNIEnv* env, jobject clazz, jlong paintPtr) {
+ const SkPaint* paint = reinterpret_cast<const SkPaint*>(paintPtr);
+ return incRef(new CanvasPropertyPaint(*paint));
+}
+
+static void unref(JNIEnv* env, jobject clazz, jlong containerPtr) {
+ reinterpret_cast<VirtualLightRefBase*>(containerPtr)->decStrong(0);
+}
+
+#endif
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/graphics/CanvasProperty";
+
+static JNINativeMethod gMethods[] = {
+#ifdef USE_OPENGL_RENDERER
+ { "nCreateFloat", "(F)J", (void*) createFloat },
+ { "nCreatePaint", "(J)J", (void*) createPaint },
+ { "nUnref", "(J)V", (void*) unref },
+#endif
+};
+
+int register_android_graphics_CanvasProperty(JNIEnv* env) {
+ return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index ef5ebd0..3aa179d 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -49,6 +49,7 @@
#include <Stencil.h>
#include <Rect.h>
#include <RenderNode.h>
+#include <CanvasProperty.h>
#include <TextLayout.h>
#include <TextLayoutCache.h>
@@ -544,6 +545,16 @@
renderer->drawCircle(x, y, radius, paint);
}
+static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
+ jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
+ OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
+ CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
+ CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
+ CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
+ renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
+}
+
static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jlong paintPtr) {
@@ -1041,6 +1052,7 @@
{ "nDrawRects", "(J[FIJ)V", (void*) android_view_GLES20Canvas_drawRects },
{ "nDrawRoundRect", "(JFFFFFFJ)V", (void*) android_view_GLES20Canvas_drawRoundRect },
{ "nDrawCircle", "(JFFFJ)V", (void*) android_view_GLES20Canvas_drawCircle },
+ { "nDrawCircle", "(JJJJJ)V", (void*) android_view_GLES20Canvas_drawCircleProps },
{ "nDrawOval", "(JFFFFJ)V", (void*) android_view_GLES20Canvas_drawOval },
{ "nDrawArc", "(JFFFFFFZJ)V", (void*) android_view_GLES20Canvas_drawArc },
{ "nDrawPoints", "(J[FIIJ)V", (void*) android_view_GLES20Canvas_drawPoints },
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index b92c992..3be013b 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -16,8 +16,6 @@
#define LOG_TAG "OpenGLRenderer"
-#include "android_view_RenderNodeAnimator.h"
-
#include "jni.h"
#include "GraphicsJNI.h"
#include <nativehelper/JNIHelp.h>
@@ -47,46 +45,93 @@
return env;
}
-RenderNodeAnimator::RenderNodeAnimator(JNIEnv* env, jobject weakThis,
- RenderProperty property, DeltaValueType deltaType, float delta)
- : RenderPropertyAnimator(property, deltaType, delta) {
- mWeakThis = env->NewGlobalRef(weakThis);
- env->GetJavaVM(&mJvm);
-}
+class AnimationListenerBridge : public AnimationListener {
+public:
+ // This holds a strong reference to a Java WeakReference<T> object. This avoids
+ // cyclic-references-of-doom. If you think "I know, just use NewWeakGlobalRef!"
+ // then you end up with basically a PhantomReference, which is totally not
+ // what we want.
+ AnimationListenerBridge(JNIEnv* env, jobject weakThis) {
+ mWeakThis = env->NewGlobalRef(weakThis);
+ env->GetJavaVM(&mJvm);
+ }
-RenderNodeAnimator::~RenderNodeAnimator() {
- JNIEnv* env = getEnv(mJvm);
- env->DeleteGlobalRef(mWeakThis);
- mWeakThis = NULL;
-}
+ virtual ~AnimationListenerBridge() {
+ JNIEnv* env = getEnv(mJvm);
+ env->DeleteGlobalRef(mWeakThis);
+ mWeakThis = NULL;
+ }
-void RenderNodeAnimator::callOnFinished() {
- JNIEnv* env = getEnv(mJvm);
- env->CallStaticVoidMethod(
- gRenderNodeAnimatorClassInfo.clazz,
- gRenderNodeAnimatorClassInfo.callOnFinished,
- mWeakThis);
-}
+ virtual void onAnimationFinished(BaseAnimator*) {
+ JNIEnv* env = getEnv(mJvm);
+ env->CallStaticVoidMethod(
+ gRenderNodeAnimatorClassInfo.clazz,
+ gRenderNodeAnimatorClassInfo.callOnFinished,
+ mWeakThis);
+ }
-static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
- jint property, jint deltaType, jfloat deltaValue) {
- LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderNodeAnimator::ALPHA,
+private:
+ JavaVM* mJvm;
+ jobject mWeakThis;
+};
+
+static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint property) {
+ LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderPropertyAnimator::ALPHA,
"Invalid property %d", property);
+ return static_cast<RenderPropertyAnimator::RenderProperty>(property);
+}
+
+static inline RenderPropertyAnimator::DeltaValueType toDeltaType(jint deltaType) {
LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA
&& deltaType != RenderPropertyAnimator::ABSOLUTE,
"Invalid delta type %d", deltaType);
+ return static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType);
+}
- RenderNodeAnimator* animator = new RenderNodeAnimator(env, weakThis,
- static_cast<RenderPropertyAnimator::RenderProperty>(property),
- static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType),
- deltaValue);
+static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) {
+ LOG_ALWAYS_FATAL_IF(field < 0
+ || field > CanvasPropertyPaintAnimator::ALPHA,
+ "Invalid paint field %d", field);
+ return static_cast<CanvasPropertyPaintAnimator::PaintField>(field);
+}
+
+static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
+ jint propertyRaw, jint deltaTypeRaw, jfloat deltaValue) {
+ RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw);
+ RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+
+ BaseAnimator* animator = new RenderPropertyAnimator(property, deltaType, deltaValue);
animator->incStrong(0);
+ animator->setListener(new AnimationListenerBridge(env, weakThis));
+ return reinterpret_cast<jlong>( animator );
+}
+
+static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz,
+ jobject weakThis, jlong canvasPropertyPtr, jint deltaTypeRaw, jfloat deltaValue) {
+ RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+ CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr);
+ BaseAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, deltaType, deltaValue);
+ animator->incStrong(0);
+ animator->setListener(new AnimationListenerBridge(env, weakThis));
+ return reinterpret_cast<jlong>( animator );
+}
+
+static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz,
+ jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw,
+ jint deltaTypeRaw, jfloat deltaValue) {
+ RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+ CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr);
+ CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw);
+ BaseAnimator* animator = new CanvasPropertyPaintAnimator(
+ canvasProperty, paintField, deltaType, deltaValue);
+ animator->incStrong(0);
+ animator->setListener(new AnimationListenerBridge(env, weakThis));
return reinterpret_cast<jlong>( animator );
}
static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) {
LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
- RenderNodeAnimator* animator = reinterpret_cast<RenderNodeAnimator*>(animatorPtr);
+ BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
animator->setDuration(duration);
}
@@ -106,6 +151,8 @@
static JNINativeMethod gMethods[] = {
#ifdef USE_OPENGL_RENDERER
{ "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator },
+ { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyFloatAnimator },
+ { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIIF)J", (void*) createCanvasPropertyPaintAnimator },
{ "nSetDuration", "(JI)V", (void*) setDuration },
{ "nUnref", "(J)V", (void*) unref },
#endif
diff --git a/core/jni/android_view_RenderNodeAnimator.h b/core/jni/android_view_RenderNodeAnimator.h
deleted file mode 100644
index 760ca91..0000000
--- a/core/jni/android_view_RenderNodeAnimator.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "jni.h"
-
-#ifdef USE_OPENGL_RENDERER
-
-#include <Animator.h>
-
-namespace android {
-
-class RenderNodeAnimator : public uirenderer::RenderPropertyAnimator {
-public:
- RenderNodeAnimator(JNIEnv* env, jobject callbackObject,
- RenderProperty property, DeltaValueType deltaType, float delta);
- virtual ~RenderNodeAnimator();
-
- void callOnFinished();
-
-private:
- JavaVM* mJvm;
- jobject mWeakThis;
-};
-
-}
-
-#endif
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 58fc1e1..564c9a6 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -26,7 +26,7 @@
#include <android_runtime/android_view_Surface.h>
#include <system/window.h>
-#include "android_view_RenderNodeAnimator.h"
+#include <Animator.h>
#include <RenderNode.h>
#include <renderthread/RenderProxy.h>
#include <renderthread/RenderTask.h>
@@ -67,26 +67,34 @@
jobject mRunnable;
};
+class OnFinishedEvent {
+public:
+ OnFinishedEvent(BaseAnimator* animator, AnimationListener* listener)
+ : animator(animator), listener(listener) {}
+ sp<BaseAnimator> animator;
+ sp<AnimationListener> listener;
+};
+
class InvokeAnimationListeners : public MessageHandler {
public:
- InvokeAnimationListeners(std::vector< sp<RenderNodeAnimator> >& animators) {
- mAnimators.swap(animators);
+ InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
+ mOnFinishedEvents.swap(events);
}
- static void callOnFinished(const sp<RenderNodeAnimator>& animator) {
- animator->callOnFinished();
+ static void callOnFinished(OnFinishedEvent& event) {
+ event.listener->onAnimationFinished(event.animator.get());
}
virtual void handleMessage(const Message& message) {
- std::for_each(mAnimators.begin(), mAnimators.end(), callOnFinished);
- mAnimators.clear();
+ std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
+ mOnFinishedEvents.clear();
}
private:
- std::vector< sp<RenderNodeAnimator> > mAnimators;
+ std::vector<OnFinishedEvent> mOnFinishedEvents;
};
-class RootRenderNode : public RenderNode, public AnimationListener {
+class RootRenderNode : public RenderNode, public AnimationHook {
public:
RootRenderNode() : RenderNode() {
mLooper = Looper::getForThread();
@@ -96,27 +104,27 @@
virtual ~RootRenderNode() {}
- void onAnimationFinished(const sp<RenderPropertyAnimator>& animator) {
- mFinishedAnimators.push_back(
- reinterpret_cast<RenderNodeAnimator*>(animator.get()));
+ virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) {
+ OnFinishedEvent event(animator, listener);
+ mOnFinishedEvents.push_back(event);
}
virtual void prepareTree(TreeInfo& info) {
- info.animationListener = this;
+ info.animationHook = this;
RenderNode::prepareTree(info);
- info.animationListener = NULL;
+ info.animationHook = NULL;
// post all the finished stuff
- if (mFinishedAnimators.size()) {
+ if (mOnFinishedEvents.size()) {
sp<InvokeAnimationListeners> message
- = new InvokeAnimationListeners(mFinishedAnimators);
+ = new InvokeAnimationListeners(mOnFinishedEvents);
mLooper->sendMessage(message, 0);
}
}
private:
sp<Looper> mLooper;
- std::vector< sp<RenderNodeAnimator> > mFinishedAnimators;
+ std::vector<OnFinishedEvent> mOnFinishedEvents;
};
static void android_view_ThreadedRenderer_postToRenderThread(JNIEnv* env, jobject clazz,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d8d8ad8..241500a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2793,7 +2793,7 @@
<receiver android:name="com.android.server.BootReceiver"
android:primaryUserOnly="true">
- <intent-filter>
+ <intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 441fd94..761170d 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -71,11 +71,7 @@
<drawable name="editbox_dropdown_dark_frame">@drawable/editbox_dropdown_background_dark</drawable>
<drawable name="editbox_dropdown_light_frame">@drawable/editbox_dropdown_background</drawable>
- <drawable name="dialog_holo_dark_frame">@drawable/dialog_full_holo_dark</drawable>
- <drawable name="dialog_holo_light_frame">@drawable/dialog_full_holo_light</drawable>
-
<drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
- <drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable>
<color name="input_method_navigation_guard">#ff000000</color>
<!-- For date picker widget -->
@@ -122,76 +118,8 @@
<!-- FaceLock -->
<color name="facelock_spotlight_mask">#CC000000</color>
- <!-- For holo theme -->
- <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
- <drawable name="screen_background_holo_dark">#ff000000</drawable>
- <color name="background_holo_dark">#ff000000</color>
- <color name="background_holo_light">#fff3f3f3</color>
- <color name="bright_foreground_holo_dark">@android:color/background_holo_light</color>
- <color name="bright_foreground_holo_light">@android:color/background_holo_dark</color>
- <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
- <color name="bright_foreground_disabled_holo_light">#ffb2b2b2</color>
- <color name="bright_foreground_inverse_holo_dark">@android:color/bright_foreground_holo_light</color>
- <color name="bright_foreground_inverse_holo_light">@android:color/bright_foreground_holo_dark</color>
- <color name="dim_foreground_holo_dark">#bebebe</color>
- <color name="dim_foreground_disabled_holo_dark">#80bebebe</color>
- <color name="dim_foreground_inverse_holo_dark">#323232</color>
- <color name="dim_foreground_inverse_disabled_holo_dark">#80323232</color>
- <color name="hint_foreground_holo_dark">#808080</color>
- <color name="dim_foreground_holo_light">#323232</color>
- <color name="dim_foreground_disabled_holo_light">#80323232</color>
- <color name="dim_foreground_inverse_holo_light">#bebebe</color>
- <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
- <color name="hint_foreground_holo_light">#808080</color>
- <color name="highlighted_text_holo_dark">#6633b5e5</color>
- <color name="highlighted_text_holo_light">#6633b5e5</color>
- <color name="link_text_holo_dark">#5c5cff</color>
- <color name="link_text_holo_light">#0000ee</color>
-
<color name="micro_text_light">#434343</color>
- <!-- Group buttons -->
- <eat-comment />
- <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
- <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
-
- <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
- <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
-
- <!-- Highlight colors for the legacy themes -->
- <eat-comment />
- <color name="legacy_pressed_highlight">#fffeaa0c</color>
- <color name="legacy_selected_highlight">#fff17a0a</color>
- <color name="legacy_long_pressed_highlight">#ffffffff</color>
-
- <!-- General purpose colors for Holo-themed elements -->
- <eat-comment />
-
- <!-- A light Holo shade of blue -->
- <color name="holo_blue_light">#ff33b5e5</color>
- <!-- A light Holo shade of gray -->
- <color name="holo_gray_light">#33999999</color>
- <!-- A light Holo shade of green -->
- <color name="holo_green_light">#ff99cc00</color>
- <!-- A light Holo shade of red -->
- <color name="holo_red_light">#ffff4444</color>
- <!-- A dark Holo shade of blue -->
- <color name="holo_blue_dark">#ff0099cc</color>
- <!-- A dark Holo shade of green -->
- <color name="holo_green_dark">#ff669900</color>
- <!-- A dark Holo shade of red -->
- <color name="holo_red_dark">#ffcc0000</color>
- <!-- A Holo shade of purple -->
- <color name="holo_purple">#ffaa66cc</color>
- <!-- A light Holo shade of orange -->
- <color name="holo_orange_light">#ffffbb33</color>
- <!-- A dark Holo shade of orange -->
- <color name="holo_orange_dark">#ffff8800</color>
- <!-- A really bright Holo shade of blue -->
- <color name="holo_blue_bright">#ff00ddff</color>
- <!-- A really bright Holo shade of gray -->
- <color name="holo_gray_bright">#33CCCCCC</color>
-
<drawable name="notification_template_icon_bg">#3333B5E5</drawable>
<drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
@@ -206,21 +134,5 @@
<color name="accessibility_focus_highlight">#80ffff00</color>
- <!-- New TimePicker colors -->
- <color name="timepicker_default_background_holo_light">@android:color/white</color>
- <color name="timepicker_default_background_holo_dark">#ff303030</color>
-
- <color name="timepicker_default_text_color_holo_light">#8c8c8c</color>
- <color name="timepicker_default_text_color_holo_dark">@android:color/white</color>
-
- <color name="timepicker_default_disabled_color_holo_light">#7f000000</color>
- <color name="timepicker_default_disabled_color_holo_dark">#7f08c8c8</color>
-
- <color name="timepicker_default_ampm_selected_background_color_holo_light">@android:color/holo_blue_light</color>
- <color name="timepicker_default_ampm_selected_background_color_holo_dark">@android:color/holo_blue_light</color>
-
- <color name="timepicker_default_ampm_unselected_background_color_holo_light">@android:color/white</color>
- <color name="timepicker_default_ampm_unselected_background_color_holo_dark">@android:color/transparent</color>
-
</resources>
diff --git a/core/res/res/values/colors_holo.xml b/core/res/res/values/colors_holo.xml
new file mode 100644
index 0000000..d1f4e38
--- /dev/null
+++ b/core/res/res/values/colors_holo.xml
@@ -0,0 +1,123 @@
+<?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.
+-->
+
+<!-- Colors specific to Holo themes. -->
+<resources>
+
+ <drawable name="dialog_holo_dark_frame">@drawable/dialog_full_holo_dark</drawable>
+ <drawable name="dialog_holo_light_frame">@drawable/dialog_full_holo_light</drawable>
+ <drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable>
+
+ <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
+ <drawable name="screen_background_holo_dark">#ff000000</drawable>
+
+ <color name="background_holo_dark">#ff000000</color>
+ <color name="background_holo_light">#fff3f3f3</color>
+ <color name="bright_foreground_holo_dark">@color/background_holo_light</color>
+ <color name="bright_foreground_holo_light">@color/background_holo_dark</color>
+ <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
+ <color name="bright_foreground_disabled_holo_light">#ffb2b2b2</color>
+ <color name="bright_foreground_inverse_holo_dark">@color/bright_foreground_holo_light</color>
+ <color name="bright_foreground_inverse_holo_light">@color/bright_foreground_holo_dark</color>
+ <color name="dim_foreground_holo_dark">#bebebe</color>
+ <color name="dim_foreground_disabled_holo_dark">#80bebebe</color>
+ <color name="dim_foreground_inverse_holo_dark">#323232</color>
+ <color name="dim_foreground_inverse_disabled_holo_dark">#80323232</color>
+ <color name="hint_foreground_holo_dark">#808080</color>
+ <color name="dim_foreground_holo_light">#323232</color>
+ <color name="dim_foreground_disabled_holo_light">#80323232</color>
+ <color name="dim_foreground_inverse_holo_light">#bebebe</color>
+ <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
+ <color name="hint_foreground_holo_light">#808080</color>
+ <color name="highlighted_text_holo_dark">#6633b5e5</color>
+ <color name="highlighted_text_holo_light">#6633b5e5</color>
+ <color name="link_text_holo_dark">#5c5cff</color>
+ <color name="link_text_holo_light">#0000ee</color>
+
+ <!-- General purpose colors for Holo-themed elements -->
+ <eat-comment />
+
+ <!-- A light Holo shade of blue -->
+ <color name="holo_blue_light">#ff33b5e5</color>
+ <!-- A light Holo shade of gray -->
+ <color name="holo_gray_light">#33999999</color>
+ <!-- A light Holo shade of green -->
+ <color name="holo_green_light">#ff99cc00</color>
+ <!-- A light Holo shade of red -->
+ <color name="holo_red_light">#ffff4444</color>
+ <!-- A dark Holo shade of blue -->
+ <color name="holo_blue_dark">#ff0099cc</color>
+ <!-- A dark Holo shade of green -->
+ <color name="holo_green_dark">#ff669900</color>
+ <!-- A dark Holo shade of red -->
+ <color name="holo_red_dark">#ffcc0000</color>
+ <!-- A Holo shade of purple -->
+ <color name="holo_purple">#ffaa66cc</color>
+ <!-- A light Holo shade of orange -->
+ <color name="holo_orange_light">#ffffbb33</color>
+ <!-- A dark Holo shade of orange -->
+ <color name="holo_orange_dark">#ffff8800</color>
+ <!-- A really bright Holo shade of blue -->
+ <color name="holo_blue_bright">#ff00ddff</color>
+ <!-- A really bright Holo shade of gray -->
+ <color name="holo_gray_bright">#33CCCCCC</color>
+
+ <!-- Forward compatibility for Quantum-style theme colors -->
+ <eat-comment />
+
+ <color name="holo_primary_dark">#ff000000</color>
+ <color name="holo_primary">#ffe6e6e6</color>
+ <color name="holo_primary_light">#ffffffff</color>
+ <color name="holo_control_activated">@color/holo_blue_light</color>
+ <color name="holo_control_normal">#39cccccc</color>
+ <color name="holo_button_pressed">#59f0f0f0</color>
+ <color name="holo_button_normal">#bd292f34</color>
+
+ <color name="holo_light_primary_dark">#ff000000</color>
+ <color name="holo_light_primary">#ffe6e6e6</color>
+ <color name="holo_light_primary_light">#ffffffff</color>
+ <color name="holo_light_control_activated">@color/holo_control_activated</color>
+ <color name="holo_light_control_normal">#dacccccc</color>
+ <color name="holo_light_button_pressed">#66666666</color>
+ <color name="holo_light_button_normal">#b3cccccc</color>
+
+ <!-- Group buttons -->
+ <eat-comment />
+
+ <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
+ <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
+
+ <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
+ <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
+
+ <!-- Time picker -->
+ <eat-comment />
+
+ <color name="timepicker_default_background_holo_light">@color/white</color>
+ <color name="timepicker_default_background_holo_dark">#ff303030</color>
+
+ <color name="timepicker_default_text_color_holo_light">#8c8c8c</color>
+ <color name="timepicker_default_text_color_holo_dark">@color/white</color>
+
+ <color name="timepicker_default_disabled_color_holo_light">#7f000000</color>
+ <color name="timepicker_default_disabled_color_holo_dark">#7f08c8c8</color>
+
+ <color name="timepicker_default_ampm_selected_background_color_holo_light">@color/holo_blue_light</color>
+ <color name="timepicker_default_ampm_selected_background_color_holo_dark">@color/holo_blue_light</color>
+
+ <color name="timepicker_default_ampm_unselected_background_color_holo_light">@color/white</color>
+ <color name="timepicker_default_ampm_unselected_background_color_holo_dark">@color/transparent</color>
+</resources>
diff --git a/core/res/res/values/colors_legacy.xml b/core/res/res/values/colors_legacy.xml
new file mode 100644
index 0000000..48d4b42
--- /dev/null
+++ b/core/res/res/values/colors_legacy.xml
@@ -0,0 +1,45 @@
+<?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.
+-->
+
+<!-- Colors specific to pre-Holo themes. -->
+<resources>
+
+ <!-- Highlight colors for the legacy themes -->
+ <eat-comment />
+
+ <color name="legacy_pressed_highlight">#fffeaa0c</color>
+ <color name="legacy_selected_highlight">#fff17a0a</color>
+ <color name="legacy_long_pressed_highlight">#ffffffff</color>
+
+ <!-- Forward compatibility for Quantum-style theme colors -->
+ <eat-comment />
+
+ <color name="legacy_primary_dark">#ff000000</color>
+ <color name="legacy_primary">#ffe6e6e6</color>
+ <color name="legacy_primary_light">#ffffffff</color>
+ <color name="legacy_control_activated">#ff90df25</color>
+ <color name="legacy_control_normal">#99ffffff</color>
+ <color name="legacy_button_pressed">#fffea50b</color>
+ <color name="legacy_button_normal">#f3dbdbdb</color>
+
+ <color name="legacy_light_primary_dark">@color/legacy_primary_dark</color>
+ <color name="legacy_light_primary">@color/legacy_primary</color>
+ <color name="legacy_light_primary_light">@color/legacy_primary_light</color>
+ <color name="legacy_light_control_activated">@color/legacy_control_activated</color>
+ <color name="legacy_light_control_normal">#99000000</color>
+ <color name="legacy_light_button_pressed">@color/legacy_button_pressed</color>
+ <color name="legacy_light_button_normal">@color/legacy_button_normal</color>
+</resources>
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index f8f192f..7171450 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
+<!-- Colors specific to Quantum themes. -->
<resources>
<color name="background_quantum_dark">@color/black</color>
<color name="background_quantum_light">@color/white</color>
@@ -40,6 +41,7 @@
<color name="highlighted_text_quantum_light">#660097a7</color>
<!-- Primary & accent colors -->
+ <eat-comment />
<color name="quantum_red_100">#fff4c7c3</color>
<color name="quantum_red_300">#ffe67c73</color>
@@ -98,6 +100,7 @@
<color name="quantum_deep_orange_A400">#ffff1744</color>
<!-- Neutral colors -->
+ <eat-comment />
<color name="quantum_grey_50">#fffafafa</color>
<color name="quantum_grey_100">#fff5f5f5</color>
@@ -117,6 +120,7 @@
<color name="quantum_brown_700">#ff5d4037</color>
<!-- Text & foreground colors -->
+ <eat-comment />
<color name="primary_text_default_quantum_light">#de000000</color>
<color name="secondary_text_quantum_light">#8a000000</color>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 22c2b050..ec73b9f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2285,8 +2285,6 @@
<public type="style" name="Widget.Quantum.Button.Inset" />
<public type="style" name="Widget.Quantum.Button.Small" />
<public type="style" name="Widget.Quantum.Button.Toggle" />
- <public type="style" name="Widget.Quantum.Button.Paper" />
- <public type="style" name="Widget.Quantum.Button.Paper.Color" />
<public type="style" name="Widget.Quantum.ButtonBar" />
<public type="style" name="Widget.Quantum.ButtonBar.AlertDialog" />
<public type="style" name="Widget.Quantum.CalendarView" />
@@ -2347,8 +2345,6 @@
<public type="style" name="Widget.Quantum.Light.Button.Inset" />
<public type="style" name="Widget.Quantum.Light.Button.Small" />
<public type="style" name="Widget.Quantum.Light.Button.Toggle" />
- <public type="style" name="Widget.Quantum.Light.Button.Paper" />
- <public type="style" name="Widget.Quantum.Light.Button.Paper.Color" />
<public type="style" name="Widget.Quantum.Light.ButtonBar" />
<public type="style" name="Widget.Quantum.Light.ButtonBar.AlertDialog" />
<public type="style" name="Widget.Quantum.Light.CalendarView" />
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 23172c1..7679420 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -372,16 +372,6 @@
<item name="minWidth">48dip</item>
</style>
- <!-- Bordered paper button -->
- <style name="Widget.Quantum.Button.Paper">
- <!-- TODO: Specify pressed state animation. -->
- </style>
-
- <!-- Bordered paper button with color -->
- <style name="Widget.Quantum.Button.Paper.Color">
- <item name="background">@drawable/btn_color_quantum</item>
- </style>
-
<!-- Borderless ink button -->
<style name="Widget.Quantum.Button.Borderless">
<item name="background">@drawable/btn_borderless_quantum</item>
@@ -393,11 +383,6 @@
<item name="minWidth">48dip</item>
</style>
- <!-- Borderless paper button -->
- <style name="Widget.Quantum.Button.Borderless.Paper">
- <!-- TODO: Specify pressed state animation. -->
- </style>
-
<style name="Widget.Quantum.Button.Inset">
<item name="background">@drawable/button_inset</item>
</style>
@@ -784,11 +769,8 @@
<style name="Widget.Quantum.Light" parent="Widget.Quantum"/>
<style name="Widget.Quantum.Light.Button" parent="Widget.Quantum.Button"/>
<style name="Widget.Quantum.Light.Button.Small" parent="Widget.Quantum.Button.Small"/>
- <style name="Widget.Quantum.Light.Button.Paper" parent="Widget.Quantum.Button.Paper"/>
- <style name="Widget.Quantum.Light.Button.Paper.Color" parent="Widget.Quantum.Button.Paper.Color"/>
<style name="Widget.Quantum.Light.Button.Borderless" parent="Widget.Quantum.Button.Borderless"/>
<style name="Widget.Quantum.Light.Button.Borderless.Small" parent="Widget.Quantum.Button.Borderless.Small"/>
- <style name="Widget.Quantum.Light.Button.Borderless.Paper" parent="Widget.Quantum.Button.Borderless.Paper"/>
<style name="Widget.Quantum.Light.Button.Inset" parent="Widget.Quantum.Button.Inset"/>
<style name="Widget.Quantum.Light.Button.Toggle">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 7b3d5e3..6f4e7d0 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -53,6 +53,14 @@
<item name="colorMultiSelectHighlight">@color/legacy_selected_highlight</item>
<item name="colorActivatedHighlight">@color/legacy_selected_highlight</item>
+ <item name="colorPrimaryDark">@color/legacy_primary_dark</item>
+ <item name="colorPrimary">@color/legacy_primary</item>
+ <item name="colorPrimaryLight">@color/legacy_primary_light</item>
+ <item name="colorControlActivated">@color/legacy_control_activated</item>
+ <item name="colorControlNormal">@color/legacy_control_normal</item>
+ <item name="colorButtonPressed">@color/legacy_button_pressed</item>
+ <item name="colorButtonNormal">@color/legacy_button_normal</item>
+
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
@@ -437,6 +445,14 @@
<item name="colorBackground">@android:color/background_light</item>
<item name="colorForeground">@color/bright_foreground_light</item>
<item name="colorForegroundInverse">@android:color/bright_foreground_light_inverse</item>
+
+ <item name="colorPrimaryDark">@color/legacy_light_primary_dark</item>
+ <item name="colorPrimary">@color/legacy_light_primary</item>
+ <item name="colorPrimaryLight">@color/legacy_light_primary_light</item>
+ <item name="colorControlActivated">@color/legacy_light_control_activated</item>
+ <item name="colorControlNormal">@color/legacy_light_control_normal</item>
+ <item name="colorButtonPressed">@color/legacy_light_button_pressed</item>
+ <item name="colorButtonNormal">@color/legacy_light_button_normal</item>
<item name="textColorPrimary">@android:color/primary_text_light</item>
<item name="textColorSecondary">@android:color/secondary_text_light</item>
@@ -937,6 +953,14 @@
<item name="colorMultiSelectHighlight">@color/holo_green_light</item>
<item name="colorActivatedHighlight">@color/holo_blue_dark</item>
+ <item name="colorPrimaryDark">@color/holo_primary_dark</item>
+ <item name="colorPrimary">@color/holo_primary</item>
+ <item name="colorPrimaryLight">@color/holo_primary_light</item>
+ <item name="colorControlActivated">@color/holo_control_activated</item>
+ <item name="colorControlNormal">@color/holo_control_normal</item>
+ <item name="colorButtonPressed">@color/holo_button_pressed</item>
+ <item name="colorButtonNormal">@color/holo_button_normal</item>
+
<!-- Text styles -->
<item name="textAppearance">@android:style/TextAppearance.Holo</item>
<item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
@@ -1268,6 +1292,14 @@
<item name="colorMultiSelectHighlight">@color/holo_green_light</item>
<item name="colorActivatedHighlight">@color/holo_blue_dark</item>
+ <item name="colorPrimaryDark">@color/holo_light_primary_dark</item>
+ <item name="colorPrimary">@color/holo_light_primary</item>
+ <item name="colorPrimaryLight">@color/holo_light_primary_light</item>
+ <item name="colorControlActivated">@color/holo_light_control_activated</item>
+ <item name="colorControlNormal">@color/holo_light_control_normal</item>
+ <item name="colorButtonPressed">@color/holo_light_button_pressed</item>
+ <item name="colorButtonNormal">@color/holo_light_button_normal</item>
+
<!-- Text styles -->
<item name="textAppearance">@android:style/TextAppearance.Holo.Light</item>
<item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Light.Inverse</item>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index e3ac1ad..c0bd18b 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -717,9 +717,6 @@
<item name="colorControlActivated">?attr/colorPrimary</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">?attr/colorPrimary</item>
- <item name="colorButtonPressedColored">?attr/colorPrimaryDark</item>
</style>
<style name="ThemeOverlay" />
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 56423c9..cfc1484 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -404,6 +404,8 @@
# key 503 KEY_BRL_DOT7
# key 504 KEY_BRL_DOT8
+key 580 APP_SWITCH
+
# Keys defined by HID usages
key usage 0x0c006F BRIGHTNESS_UP
key usage 0x0c0070 BRIGHTNESS_DOWN
diff --git a/graphics/java/android/graphics/CanvasProperty.java b/graphics/java/android/graphics/CanvasProperty.java
new file mode 100644
index 0000000..99ea9b1
--- /dev/null
+++ b/graphics/java/android/graphics/CanvasProperty.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+/**
+ * TODO: Make public?
+ * @hide
+ */
+public final class CanvasProperty<T> {
+ private long mNativeContainer;
+
+ public static CanvasProperty<Float> createFloat(float initialValue) {
+ return new CanvasProperty<Float>(nCreateFloat(initialValue));
+ }
+
+ public static CanvasProperty<Paint> createPaint(Paint initialValue) {
+ return new CanvasProperty<Paint>(nCreatePaint(initialValue.mNativePaint));
+ }
+
+ private CanvasProperty(long nativeContainer) {
+ mNativeContainer = nativeContainer;
+ }
+
+ /** @hide */
+ public long getNativeContainer() {
+ return mNativeContainer;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ nUnref(mNativeContainer);
+ mNativeContainer = 0;
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private static native long nCreateFloat(float initialValue);
+ private static native long nCreatePaint(long initialValuePaintPtr);
+ private static native void nUnref(long ptr);
+}
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index e08ed50..062acaf 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -253,4 +253,31 @@
}
return -1;
}
+
+ /**
+ * Determine whether or not this is a public-visible {@code format}.
+ *
+ * <p>In particular, {@code @hide} formats will return {@code false}.</p>
+ *
+ * <p>Any other formats (including UNKNOWN) will return {@code false}.</p>
+ *
+ * @param format an integer format
+ * @return a boolean
+ *
+ * @hide
+ */
+ public static boolean isPublicFormat(int format) {
+ switch (format) {
+ case RGB_565:
+ case NV16:
+ case YUY2:
+ case YV12:
+ case NV21:
+ case YUV_420_888:
+ case RAW_SENSOR:
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index d96d6d8..832b9c3 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -115,7 +115,7 @@
info.bytesPerPixel = 1;
break;
default:
- throw new IllegalArgumentException("unkonwon pixel format " + format);
+ throw new IllegalArgumentException("unknown pixel format " + format);
}
}
@@ -135,4 +135,29 @@
public int bytesPerPixel;
public int bitsPerPixel;
+
+ /**
+ * Determine whether or not this is a public-visible and non-deprecated {@code format}.
+ *
+ * <p>In particular, {@code @hide} formats will return {@code false}.</p>
+ *
+ * <p>Any other indirect formats (such as {@code TRANSPARENT} or {@code TRANSLUCENT})
+ * will return {@code false}.</p>
+ *
+ * @param format an integer format
+ * @return a boolean
+ *
+ * @hide
+ */
+ public static boolean isPublicFormat(int format) {
+ switch (format) {
+ case RGBA_8888:
+ case RGBX_8888:
+ case RGB_888:
+ case RGB_565:
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 3446000..218a057 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -299,7 +299,7 @@
*/
public void cancel() {
if (mInner != null) {
- mInner.end();
+ mInner.cancel();
}
if (mOuter != null) {
@@ -307,7 +307,7 @@
}
if (mAlpha != null) {
- mAlpha.end();
+ mAlpha.cancel();
}
}
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index ee16586..6a3003e 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -20,130 +20,13 @@
#include <set>
+#include "RenderNode.h"
#include "RenderProperties.h"
namespace android {
namespace uirenderer {
/************************************************************
- * Private header
- ************************************************************/
-
-typedef void (RenderProperties::*SetFloatProperty)(float value);
-typedef float (RenderProperties::*GetFloatProperty)() const;
-
-struct PropertyAccessors {
- GetFloatProperty getter;
- SetFloatProperty setter;
-};
-
-// Maps RenderProperty enum to accessors
-static const PropertyAccessors PROPERTY_ACCESSOR_LUT[] = {
- {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
- {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
- {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
- {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
- {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
- {&RenderProperties::getRotation, &RenderProperties::setRotation },
- {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
- {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
- {&RenderProperties::getX, &RenderProperties::setX },
- {&RenderProperties::getY, &RenderProperties::setY },
- {&RenderProperties::getZ, &RenderProperties::setZ },
- {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
-};
-
-// Helper class to contain generic animator helpers
-class BaseAnimator {
-public:
- BaseAnimator();
- virtual ~BaseAnimator();
-
- void setInterpolator(Interpolator* interpolator);
- void setDuration(nsecs_t durationInMs);
-
- bool isFinished() { return mPlayState == FINISHED; }
-
-protected:
- // This is the main animation entrypoint that subclasses should call
- // to generate the onAnimation* lifecycle events
- // Returns true if the animation has finished, false otherwise
- bool animateFrame(nsecs_t frameTime);
-
- // Called when PlayState switches from PENDING to RUNNING
- virtual void onAnimationStarted() {}
- virtual void onAnimationUpdated(float fraction) = 0;
- virtual void onAnimationFinished() {}
-
-private:
- enum PlayState {
- PENDING,
- RUNNING,
- FINISHED,
- };
-
- Interpolator* mInterpolator;
- PlayState mPlayState;
- long mStartTime;
- long mDuration;
-};
-
-// Hide the base classes & private bits from the exported RenderPropertyAnimator
-// in this Impl class so that subclasses of RenderPropertyAnimator don't require
-// knowledge of the inner guts but only the public virtual methods.
-// Animates a single property
-class RenderPropertyAnimatorImpl : public BaseAnimator {
-public:
- RenderPropertyAnimatorImpl(GetFloatProperty getter, SetFloatProperty setter,
- RenderPropertyAnimator::DeltaValueType deltaType, float delta);
- ~RenderPropertyAnimatorImpl();
-
- bool animate(RenderProperties* target, TreeInfo& info);
-
-protected:
- virtual void onAnimationStarted();
- virtual void onAnimationUpdated(float fraction);
-
-private:
- // mTarget is only valid inside animate()
- RenderProperties* mTarget;
- GetFloatProperty mGetter;
- SetFloatProperty mSetter;
-
- RenderPropertyAnimator::DeltaValueType mDeltaValueType;
- float mDeltaValue;
- float mFromValue;
-};
-
-RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
- DeltaValueType deltaType, float deltaValue) {
- PropertyAccessors pa = PROPERTY_ACCESSOR_LUT[property];
- mImpl = new RenderPropertyAnimatorImpl(pa.getter, pa.setter, deltaType, deltaValue);
-}
-
-RenderPropertyAnimator::~RenderPropertyAnimator() {
- delete mImpl;
- mImpl = NULL;
-}
-
-void RenderPropertyAnimator::setInterpolator(Interpolator* interpolator) {
- mImpl->setInterpolator(interpolator);
-}
-
-void RenderPropertyAnimator::setDuration(nsecs_t durationInMs) {
- mImpl->setDuration(durationInMs);
-}
-
-bool RenderPropertyAnimator::isFinished() {
- return mImpl->isFinished();
-}
-
-bool RenderPropertyAnimator::animate(RenderProperties* target, TreeInfo& info) {
- return mImpl->animate(target, info);
-}
-
-
-/************************************************************
* Base animator
************************************************************/
@@ -168,10 +51,10 @@
mDuration = duration;
}
-bool BaseAnimator::animateFrame(nsecs_t frameTime) {
+bool BaseAnimator::animateFrame(TreeInfo& info) {
if (mPlayState == PENDING) {
mPlayState = RUNNING;
- mStartTime = frameTime;
+ mStartTime = info.frameTimeMs;
// No interpolator was set, use the default
if (!mInterpolator) {
setInterpolator(Interpolator::createDefaultInterpolator());
@@ -181,7 +64,7 @@
float fraction = 1.0f;
if (mPlayState == RUNNING) {
- fraction = mDuration > 0 ? (float)(frameTime - mStartTime) / mDuration : 1.0f;
+ fraction = mDuration > 0 ? (float)(info.frameTimeMs - mStartTime) / mDuration : 1.0f;
if (fraction >= 1.0f) {
fraction = 1.0f;
mPlayState = FINISHED;
@@ -192,48 +75,140 @@
if (mPlayState == FINISHED) {
onAnimationFinished();
+ callOnFinishedListener(info);
return true;
}
return false;
}
+void BaseAnimator::callOnFinishedListener(TreeInfo& info) {
+ if (mListener.get()) {
+ if (!info.animationHook) {
+ mListener->onAnimationFinished(this);
+ } else {
+ info.animationHook->callOnFinished(this, mListener.get());
+ }
+ }
+}
+
+/************************************************************
+ * BaseRenderNodeAnimator
+ ************************************************************/
+
+BaseRenderNodeAnimator::BaseRenderNodeAnimator(
+ BaseRenderNodeAnimator::DeltaValueType deltaType, float delta)
+ : mTarget(0)
+ , mDeltaValueType(deltaType)
+ , mDeltaValue(delta)
+ , mFromValue(-1) {
+}
+
+bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
+ mTarget = target;
+ bool finished = animateFrame(info);
+ mTarget = NULL;
+ return finished;
+}
+
+void BaseRenderNodeAnimator::onAnimationStarted() {
+ mFromValue = getValue();
+
+ if (mDeltaValueType == BaseRenderNodeAnimator::ABSOLUTE) {
+ mDeltaValue = (mDeltaValue - mFromValue);
+ mDeltaValueType = BaseRenderNodeAnimator::DELTA;
+ }
+}
+
+void BaseRenderNodeAnimator::onAnimationUpdated(float fraction) {
+ float value = mFromValue + (mDeltaValue * fraction);
+ setValue(value);
+}
+
/************************************************************
* RenderPropertyAnimator
************************************************************/
-RenderPropertyAnimatorImpl::RenderPropertyAnimatorImpl(
- GetFloatProperty getter, SetFloatProperty setter,
- RenderPropertyAnimator::DeltaValueType deltaType, float delta)
- : mTarget(0)
- , mGetter(getter)
- , mSetter(setter)
- , mDeltaValueType(deltaType)
- , mDeltaValue(delta)
- , mFromValue(-1) {
+// Maps RenderProperty enum to accessors
+const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
+ {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
+ {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
+ {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
+ {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
+ {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
+ {&RenderProperties::getRotation, &RenderProperties::setRotation },
+ {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
+ {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
+ {&RenderProperties::getX, &RenderProperties::setX },
+ {&RenderProperties::getY, &RenderProperties::setY },
+ {&RenderProperties::getZ, &RenderProperties::setZ },
+ {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
+};
+
+RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
+ DeltaValueType deltaType, float deltaValue)
+ : BaseRenderNodeAnimator(deltaType, deltaValue)
+ , mPropertyAccess(PROPERTY_ACCESSOR_LUT[property]) {
}
-RenderPropertyAnimatorImpl::~RenderPropertyAnimatorImpl() {
+float RenderPropertyAnimator::getValue() const {
+ return (target()->animatorProperties().*mPropertyAccess.getter)();
}
-bool RenderPropertyAnimatorImpl::animate(RenderProperties* target, TreeInfo& info) {
- mTarget = target;
- bool finished = animateFrame(info.frameTimeMs);
- mTarget = NULL;
- return finished;
+void RenderPropertyAnimator::setValue(float value) {
+ (target()->animatorProperties().*mPropertyAccess.setter)(value);
}
-void RenderPropertyAnimatorImpl::onAnimationStarted() {
- mFromValue = (mTarget->*mGetter)();
+/************************************************************
+ * CanvasPropertyPrimitiveAnimator
+ ************************************************************/
- if (mDeltaValueType == RenderPropertyAnimator::ABSOLUTE) {
- mDeltaValue = (mDeltaValue - mFromValue);
- mDeltaValueType = RenderPropertyAnimator::DELTA;
+CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
+ CanvasPropertyPrimitive* property, DeltaValueType deltaType, float deltaValue)
+ : BaseRenderNodeAnimator(deltaType, deltaValue)
+ , mProperty(property) {
+}
+
+float CanvasPropertyPrimitiveAnimator::getValue() const {
+ return mProperty->value;
+}
+
+void CanvasPropertyPrimitiveAnimator::setValue(float value) {
+ mProperty->value = value;
+}
+
+/************************************************************
+ * CanvasPropertySkPaintAnimator
+ ************************************************************/
+
+CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
+ CanvasPropertyPaint* property, PaintField field,
+ DeltaValueType deltaType, float deltaValue)
+ : BaseRenderNodeAnimator(deltaType, deltaValue)
+ , mProperty(property)
+ , mField(field) {
+}
+
+float CanvasPropertyPaintAnimator::getValue() const {
+ switch (mField) {
+ case STROKE_WIDTH:
+ return mProperty->value.getStrokeWidth();
+ case ALPHA:
+ return mProperty->value.getAlpha();
}
+ LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
+ return -1;
}
-void RenderPropertyAnimatorImpl::onAnimationUpdated(float fraction) {
- float value = mFromValue + (mDeltaValue * fraction);
- (mTarget->*mSetter)(value);
+void CanvasPropertyPaintAnimator::setValue(float value) {
+ switch (mField) {
+ case STROKE_WIDTH:
+ mProperty->value.setStrokeWidth(value);
+ return;
+ case ALPHA:
+ mProperty->value.setAlpha(value);
+ return;
+ }
+ LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
}
} /* namespace uirenderer */
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 1c8361b..0b074cc 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -17,18 +17,72 @@
#define ANIMATOR_H
#include <cutils/compiler.h>
+#include <utils/StrongPointer.h>
+#include "CanvasProperty.h"
#include "Interpolator.h"
#include "TreeInfo.h"
+#include "utils/Macros.h"
#include "utils/VirtualLightRefBase.h"
namespace android {
namespace uirenderer {
+class RenderNode;
class RenderProperties;
-class RenderPropertyAnimatorImpl;
-class RenderPropertyAnimator : public VirtualLightRefBase {
+class AnimationListener : public VirtualLightRefBase {
+public:
+ ANDROID_API virtual void onAnimationFinished(BaseAnimator*) = 0;
+protected:
+ ANDROID_API virtual ~AnimationListener() {}
+};
+
+// Helper class to contain generic animator helpers
+class BaseAnimator : public VirtualLightRefBase {
+ PREVENT_COPY_AND_ASSIGN(BaseAnimator);
+public:
+
+ ANDROID_API void setInterpolator(Interpolator* interpolator);
+ ANDROID_API void setDuration(nsecs_t durationInMs);
+ ANDROID_API void setListener(AnimationListener* listener) {
+ mListener = listener;
+ }
+
+ bool isFinished() { return mPlayState == FINISHED; }
+
+protected:
+ BaseAnimator();
+ virtual ~BaseAnimator();
+
+ // This is the main animation entrypoint that subclasses should call
+ // to generate the onAnimation* lifecycle events
+ // Returns true if the animation has finished, false otherwise
+ bool animateFrame(TreeInfo& info);
+
+ // Called when PlayState switches from PENDING to RUNNING
+ virtual void onAnimationStarted() {}
+ virtual void onAnimationUpdated(float fraction) = 0;
+ virtual void onAnimationFinished() {}
+
+private:
+ void callOnFinishedListener(TreeInfo& info);
+
+ enum PlayState {
+ PENDING,
+ RUNNING,
+ FINISHED,
+ };
+
+ Interpolator* mInterpolator;
+ PlayState mPlayState;
+ long mStartTime;
+ long mDuration;
+
+ sp<AnimationListener> mListener;
+};
+
+class BaseRenderNodeAnimator : public BaseAnimator {
public:
// Since the UI thread doesn't necessarily know what the current values
// actually are and thus can't do the calculations, this is used to inform
@@ -43,6 +97,29 @@
DELTA,
};
+ bool animate(RenderNode* target, TreeInfo& info);
+
+protected:
+ BaseRenderNodeAnimator(DeltaValueType deltaType, float deltaValue);
+
+ RenderNode* target() const { return mTarget; }
+ virtual float getValue() const = 0;
+ virtual void setValue(float value) = 0;
+
+private:
+ virtual void onAnimationStarted();
+ virtual void onAnimationUpdated(float fraction);
+
+ // mTarget is only valid inside animate()
+ RenderNode* mTarget;
+
+ BaseRenderNodeAnimator::DeltaValueType mDeltaValueType;
+ float mDeltaValue;
+ float mFromValue;
+};
+
+class RenderPropertyAnimator : public BaseRenderNodeAnimator {
+public:
enum RenderProperty {
TRANSLATION_X = 0,
TRANSLATION_Y,
@@ -58,19 +135,53 @@
ALPHA,
};
- ANDROID_API void setInterpolator(Interpolator* interpolator);
- ANDROID_API void setDuration(nsecs_t durationInMs);
- ANDROID_API bool isFinished();
-
- bool animate(RenderProperties* target, TreeInfo& info);
+ ANDROID_API RenderPropertyAnimator(RenderProperty property,
+ DeltaValueType deltaType, float deltaValue);
protected:
- ANDROID_API RenderPropertyAnimator(RenderProperty property, DeltaValueType deltaType,
- float deltaValue);
- ANDROID_API virtual ~RenderPropertyAnimator();
+ ANDROID_API virtual float getValue() const;
+ ANDROID_API virtual void setValue(float value);
private:
- RenderPropertyAnimatorImpl* mImpl;
+ typedef void (RenderProperties::*SetFloatProperty)(float value);
+ typedef float (RenderProperties::*GetFloatProperty)() const;
+
+ struct PropertyAccessors {
+ GetFloatProperty getter;
+ SetFloatProperty setter;
+ };
+
+ PropertyAccessors mPropertyAccess;
+
+ static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
+};
+
+class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
+public:
+ ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
+ DeltaValueType deltaType, float deltaValue);
+protected:
+ ANDROID_API virtual float getValue() const;
+ ANDROID_API virtual void setValue(float value);
+private:
+ sp<CanvasPropertyPrimitive> mProperty;
+};
+
+class CanvasPropertyPaintAnimator : public BaseRenderNodeAnimator {
+public:
+ enum PaintField {
+ STROKE_WIDTH = 0,
+ ALPHA,
+ };
+
+ ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
+ PaintField field, DeltaValueType deltaType, float deltaValue);
+protected:
+ ANDROID_API virtual float getValue() const;
+ ANDROID_API virtual void setValue(float value);
+private:
+ sp<CanvasPropertyPaint> mProperty;
+ PaintField mField;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/CanvasProperty.h b/libs/hwui/CanvasProperty.h
new file mode 100644
index 0000000..2e1d176
--- /dev/null
+++ b/libs/hwui/CanvasProperty.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef CANVASPROPERTY_H
+#define CANVASPROPERTY_H
+
+#include "utils/Macros.h"
+#include "utils/VirtualLightRefBase.h"
+
+#include <SkPaint.h>
+
+namespace android {
+namespace uirenderer {
+
+class CanvasPropertyPrimitive : public VirtualLightRefBase {
+ PREVENT_COPY_AND_ASSIGN(CanvasPropertyPrimitive);
+public:
+ CanvasPropertyPrimitive(float initialValue) : value(initialValue) {}
+
+ float value;
+};
+
+class CanvasPropertyPaint : public VirtualLightRefBase {
+ PREVENT_COPY_AND_ASSIGN(CanvasPropertyPaint);
+public:
+ CanvasPropertyPaint(const SkPaint& initialValue) : value(initialValue) {}
+
+ SkPaint value;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* CANVASPROPERTY_H */
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index fe70d13..eaeb772 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -140,6 +140,14 @@
void addChild(DrawDisplayListOp* childOp);
const Vector<DrawDisplayListOp*>& children() { return mChildren; }
+ void refProperty(CanvasPropertyPrimitive* prop) {
+ mReferenceHolders.push(prop);
+ }
+
+ void refProperty(CanvasPropertyPaint* prop) {
+ mReferenceHolders.push(prop);
+ }
+
private:
Vector< sp<VirtualLightRefBase> > mReferenceHolders;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 6dfb918..ce92beb 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1198,6 +1198,27 @@
float mRadius;
};
+class DrawCirclePropsOp : public DrawOp {
+public:
+ DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
+ : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
+
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
+ return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
+ }
+
+ virtual void output(int level, uint32_t logFlags) const {
+ OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
+ }
+
+ virtual const char* name() { return "DrawCircleProps"; }
+
+private:
+ float* mX;
+ float* mY;
+ float* mRadius;
+};
+
class DrawOvalOp : public DrawStrokableOp {
public:
DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index e36d975..8afd106 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -299,6 +299,17 @@
return DrawGlInfo::kStatusDone;
}
+status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+ CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+ mDisplayListData->refProperty(x);
+ mDisplayListData->refProperty(y);
+ mDisplayListData->refProperty(radius);
+ mDisplayListData->refProperty(paint);
+ addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
+ &radius->value, &paint->value));
+ return DrawGlInfo::kStatusDone;
+}
+
status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
const SkPaint* paint) {
paint = refPaint(paint);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 04c5a73..25e78c1 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -135,6 +135,8 @@
virtual status_t drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, const SkPaint* paint);
virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+ virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+ CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
virtual status_t drawOval(float left, float top, float right, float bottom,
const SkPaint* paint);
virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b49d1e1..7794abc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -49,6 +49,7 @@
#include "UvMapper.h"
#include "Vertex.h"
#include "Caches.h"
+#include "CanvasProperty.h"
namespace android {
namespace uirenderer {
@@ -200,6 +201,12 @@
virtual status_t drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, const SkPaint* paint);
virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+ virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+ CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+ // TODO: Remove once android_view_GLES20Canvas uses DisplayListRenderer
+ // directly
+ return drawCircle(x->value, y->value, radius->value, &paint->value);
+ }
virtual status_t drawOval(float left, float top, float right, float bottom,
const SkPaint* paint);
virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 7a9c181..2c29985 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -109,7 +109,7 @@
prepareSubTree(info, mDisplayListData);
}
-static bool is_finished(const sp<RenderPropertyAnimator>& animator) {
+static bool is_finished(const sp<BaseRenderNodeAnimator>& animator) {
return animator->isFinished();
}
@@ -120,7 +120,7 @@
}
if (mNeedsAnimatorsSync) {
mAnimators.resize(mStagingAnimators.size());
- std::vector< sp<RenderPropertyAnimator> >::iterator it;
+ std::vector< sp<BaseRenderNodeAnimator> >::iterator it;
// hint: this means copy_if_not()
it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
mAnimators.begin(), is_finished);
@@ -141,26 +141,22 @@
class AnimateFunctor {
public:
- AnimateFunctor(RenderProperties* target, TreeInfo& info)
+ AnimateFunctor(RenderNode* target, TreeInfo& info)
: mTarget(target), mInfo(info) {}
- bool operator() (sp<RenderPropertyAnimator>& animator) {
- bool finished = animator->animate(mTarget, mInfo);
- if (finished && mInfo.animationListener) {
- mInfo.animationListener->onAnimationFinished(animator);
- }
- return finished;
+ bool operator() (sp<BaseRenderNodeAnimator>& animator) {
+ return animator->animate(mTarget, mInfo);
}
private:
- RenderProperties* mTarget;
+ RenderNode* mTarget;
TreeInfo& mInfo;
};
void RenderNode::evaluateAnimations(TreeInfo& info) {
if (!mAnimators.size()) return;
- AnimateFunctor functor(&mProperties, info);
- std::vector< sp<RenderPropertyAnimator> >::iterator newEnd;
+ AnimateFunctor functor(this, info);
+ std::vector< sp<BaseRenderNodeAnimator> >::iterator newEnd;
newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
mAnimators.erase(newEnd, mAnimators.end());
mProperties.updateMatrix();
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 294f436..159903c 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -128,6 +128,10 @@
return mProperties;
}
+ RenderProperties& animatorProperties() {
+ return mProperties;
+ }
+
const RenderProperties& stagingProperties() {
return mStagingProperties;
}
@@ -148,13 +152,13 @@
ANDROID_API virtual void prepareTree(TreeInfo& info);
// UI thread only!
- ANDROID_API void addAnimator(const sp<RenderPropertyAnimator>& animator) {
+ ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
mStagingAnimators.insert(animator);
mNeedsAnimatorsSync = true;
}
// UI thread only!
- ANDROID_API void removeAnimator(const sp<RenderPropertyAnimator>& animator) {
+ ANDROID_API void removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
mStagingAnimators.erase(animator);
mNeedsAnimatorsSync = true;
}
@@ -233,8 +237,8 @@
DisplayListData* mStagingDisplayListData;
bool mNeedsAnimatorsSync;
- std::set< sp<RenderPropertyAnimator> > mStagingAnimators;
- std::vector< sp<RenderPropertyAnimator> > mAnimators;
+ std::set< sp<BaseRenderNodeAnimator> > mStagingAnimators;
+ std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
/**
* Draw time state - these properties are only set and used during rendering
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 8957607..a383fbf 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -16,20 +16,19 @@
#ifndef TREEINFO_H
#define TREEINFO_H
-#include <cutils/compiler.h>
#include <utils/Timers.h>
-#include <utils/StrongPointer.h>
namespace android {
namespace uirenderer {
-class RenderPropertyAnimator;
+class BaseAnimator;
+class AnimationListener;
-class AnimationListener {
+class AnimationHook {
public:
- ANDROID_API virtual void onAnimationFinished(const sp<RenderPropertyAnimator>&) = 0;
+ virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) = 0;
protected:
- ANDROID_API virtual ~AnimationListener() {}
+ ~AnimationHook() {}
};
struct TreeInfo {
@@ -41,7 +40,7 @@
, frameTimeMs(0)
, evaluateAnimations(false)
, hasAnimations(false)
- , animationListener(0)
+ , animationHook(0)
{}
bool hasFunctors;
@@ -53,7 +52,7 @@
bool evaluateAnimations;
// This is only updated if evaluateAnimations is true
bool hasAnimations;
- AnimationListener* animationListener;
+ AnimationHook* animationHook;
// TODO: Damage calculations
};
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index ff4be71..45f5cb0 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -112,6 +112,10 @@
initTreeInfo(info);
mContext->processLayerUpdates(&mLayers, info);
mContext->prepareTree(info);
+ if (info.hasAnimations) {
+ // TODO: dirty calculations, for now just do a full-screen inval
+ mDirty.setEmpty();
+ }
// If prepareTextures is false, we ran out of texture cache space
return !info.hasFunctors && info.prepareTextures;
}
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
new file mode 100644
index 0000000..14a3ec0
--- /dev/null
+++ b/libs/hwui/utils/Macros.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MACROS_H
+#define MACROS_H
+
+#define PREVENT_COPY_AND_ASSIGN(Type) \
+ private: \
+ Type(const Type&); \
+ void operator=(const Type&)
+
+
+#endif /* MACROS_H */
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 327df8d..e6cdda0 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -138,7 +138,7 @@
android:exported="true" />
<receiver android:name=".BootReceiver" androidprv:primaryUserOnly="true">
- <intent-filter>
+ <intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 103991a..217074f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -65,6 +65,8 @@
// the theme set there.
setTheme(R.style.systemui_theme);
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -80,7 +82,7 @@
}
}
}
- }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ }, filter);
}
/**
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index 77d5076..2fa23c9 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -125,8 +125,10 @@
// Register for the boot completed broadcast, so we can send the
// ENABLE broacasts. If we try to send them now, they time out,
// because the system isn't ready to handle them yet.
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+ filter, null, null);
// Register for configuration changes so we can update the names
// of the widgets when the locale changes.
@@ -135,7 +137,6 @@
// Register for broadcasts about package install, etc., so we can
// update the provider list.
- IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 0d6f548..e2a8ca2 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -212,6 +212,7 @@
filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
registerForAirplaneMode(filter);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(mReceiver, filter);
loadStoredNameAndAddress();
if (isBluetoothPersistedStateOn()) {
diff --git a/services/core/java/com/android/server/RecognitionManagerService.java b/services/core/java/com/android/server/RecognitionManagerService.java
index c2e749d..60d38ae 100644
--- a/services/core/java/com/android/server/RecognitionManagerService.java
+++ b/services/core/java/com/android/server/RecognitionManagerService.java
@@ -78,8 +78,10 @@
mMonitor = new MyPackageMonitor();
mMonitor.register(context, null, UserHandle.ALL, true);
mIPm = AppGlobals.getPackageManager();
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+ filter, null, null);
}
public void systemReady() {
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index 415fcc1..50cfe48 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -97,13 +97,15 @@
mObserver = new WiredAccessoryObserver();
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context ctx, Intent intent) {
bootCompleted();
}
},
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+ filter, null, null);
}
private void bootCompleted() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 042bf5f..bcc6359 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15186,8 +15186,8 @@
// it when computing the final cached adj later. Note that we don't need to
// worry about this for max adj above, since max adj will always be used to
// keep it out of the cached vaues.
- adj = app.modifyRawOomAdj(adj);
-
+ app.curAdj = app.modifyRawOomAdj(adj);
+ app.curSchedGroup = schedGroup;
app.curProcState = procState;
app.foregroundActivities = foregroundActivities;
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 026fd296..1b40cdf 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -411,6 +411,7 @@
if (!factoryTest) {
intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
context.registerReceiver(mBootCompletedReceiver, intentFilter);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 14df347..3239b46 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1092,6 +1092,9 @@
// on next startup, in case the runtime stops now before stopping and
// removing the user completely.
user.partial = true;
+ // Mark it as disabled, so that it isn't returned any more when
+ // profiles are queried.
+ user.flags |= UserInfo.FLAG_DISABLED;
writeUserLocked(user);
}
if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
@@ -1120,6 +1123,7 @@
// wiping the user's system directory and removing from the user list
long ident = Binder.clearCallingIdentity();
try {
+ final boolean isManaged = getUserInfo(userHandle).isManagedProfile();
Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
@@ -1140,6 +1144,11 @@
removeUserStateLocked(userHandle);
}
}
+ // Send broadcast to notify system that the user removed was a
+ // managed user.
+ if (isManaged) {
+ sendProfileRemovedBroadcast(userHandle);
+ }
}
}.start();
}
@@ -1191,6 +1200,13 @@
parent.delete();
}
+ private void sendProfileRemovedBroadcast(int userHandle) {
+ Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+ managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(userHandle));
+ // Note: This makes an assumption that the parent owner is user 0.
+ mContext.sendBroadcastAsUser(managedProfileIntent, UserHandle.OWNER, null);
+ }
+
@Override
public Bundle getApplicationRestrictions(String packageName) {
return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index cfe24fe..6d2e8592 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -496,6 +496,7 @@
filter = new IntentFilter();
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(new BootCompletedReceiver(), filter, null, mHandler);
filter = new IntentFilter();
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index 486477a..5deb2b8 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -70,8 +70,9 @@
*/
public SearchManagerService(Context context) {
mContext = context;
- mContext.registerReceiver(new BootCompletedReceiver(),
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ mContext.registerReceiver(new BootCompletedReceiver(), filter);
mContext.registerReceiver(new UserReceiver(),
new IntentFilter(Intent.ACTION_USER_REMOVED));
new MyPackageMonitor().register(context, null, UserHandle.ALL, true);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index aaa97eb..d0a6db1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -588,6 +588,7 @@
filter.addAction(Intent.ACTION_USER_REMOVED);
filter.addAction(Intent.ACTION_USER_STARTED);
filter.addAction(KeyChain.ACTION_STORAGE_CHANGED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index f5ac178..6822ee3 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -373,8 +373,9 @@
mUEventObserver.startObserving(USB_STATE_MATCH);
mUEventObserver.startObserving(ACCESSORY_START_MATCH);
- mContext.registerReceiver(
- mBootCompletedReceiver, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ mContext.registerReceiver(mBootCompletedReceiver, filter);
mContext.registerReceiver(
mUserSwitchedReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
} catch (Exception e) {
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 5c2583b..af0d0ad 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -288,6 +288,15 @@
</activity>
<activity
+ android:name="CirclePropActivity"
+ android:label="Draw/Circle Props">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.hwui.TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="ClearActivity"
android:label="Window/Clear">
<intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
new file mode 100644
index 0000000..f060bc8
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.os.Bundle;
+import android.os.Trace;
+import android.view.HardwareCanvas;
+import android.view.RenderNodeAnimator;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.ProgressBar;
+
+import java.util.ArrayList;
+
+public class CirclePropActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+
+ ProgressBar spinner = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge);
+ layout.addView(spinner, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+
+ layout.addView(new CircleView(this),
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+ setContentView(layout);
+ }
+
+ static class CircleView extends View {
+ static final int DURATION = 500;
+
+ private boolean mToggle = false;
+ ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<RenderNodeAnimator>();
+
+ CanvasProperty<Float> mX;
+ CanvasProperty<Float> mY;
+ CanvasProperty<Float> mRadius;
+ CanvasProperty<Paint> mPaint;
+
+ CircleView(Context c) {
+ super(c);
+ setClickable(true);
+
+ mX = CanvasProperty.createFloat(200.0f);
+ mY = CanvasProperty.createFloat(200.0f);
+ mRadius = CanvasProperty.createFloat(150.0f);
+
+ Paint p = new Paint();
+ p.setAntiAlias(true);
+ p.setColor(0xFFFF0000);
+ p.setStyle(Style.STROKE);
+ p.setStrokeWidth(60.0f);
+ mPaint = CanvasProperty.createPaint(p);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (canvas.isHardwareAccelerated()) {
+ HardwareCanvas hwcanvas = (HardwareCanvas) canvas;
+ hwcanvas.drawCircle(mX, mY, mRadius, mPaint);
+ }
+ }
+
+ @Override
+ public boolean performClick() {
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ mRunningAnimations.get(i).cancel();
+ }
+ mRunningAnimations.clear();
+
+ mToggle = !mToggle;
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mX, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 400.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mY, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 600.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mRadius, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 250.0f : 150.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_ALPHA,
+ RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 64.0f : 255.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_STROKE_WIDTH,
+ RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 5.0f : 60.0f));
+
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ mRunningAnimations.get(i).start(this);
+ }
+
+ if (mToggle) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "pretendBusy");
+ try {
+ Thread.sleep(DURATION);
+ } catch (InterruptedException e) {
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ });
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
index 8c02539..a3f4ddc 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
@@ -57,7 +57,7 @@
mPaint = new Paint();
mPaint.setAntiAlias(true);
- mPaint.setColor(0xffffffff);
+ mPaint.setColor(0xff00ffff);
}
@Override
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index 1d209dd..8f9cf58 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -19,8 +19,6 @@
public class MainActivity extends Activity implements OnItemClickListener {
- static final int TRANSLATION_Y = 1;
- static final int DELTA_TYPE_DELTA = 1;
static final int DURATION = 400;
static final String KEY_NAME = "name";
@@ -75,7 +73,7 @@
float delta = (pos - clickedPosition) * 1.1f;
if (delta == 0) delta = -1;
RenderNodeAnimator animator = new RenderNodeAnimator(
- TRANSLATION_Y, DELTA_TYPE_DELTA, dy * delta);
+ RenderNodeAnimator.TRANSLATION_Y, RenderNodeAnimator.DELTA_TYPE_DELTA, dy * delta);
animator.setDuration(DURATION);
animator.start(child);
}