diff options
135 files changed, 2397 insertions, 1796 deletions
diff --git a/api/current.txt b/api/current.txt index efadf77..a543cbf 100644 --- a/api/current.txt +++ b/api/current.txt @@ -865,6 +865,7 @@ package android { field public static final int permissionFlags = 16843719; // 0x10103c7 field public static final int permissionGroup = 16842762; // 0x101000a field public static final int permissionGroupFlags = 16843717; // 0x10103c5 + field public static final int persistable = 16843832; // 0x1010438 field public static final int persistent = 16842765; // 0x101000d field public static final int persistentDrawingCache = 16842990; // 0x10100ee field public static final deprecated int phoneNumber = 16843111; // 0x1010167 @@ -1821,46 +1822,50 @@ package android { 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 = 16974346; // 0x103020a - field public static final int TextAppearance_Quantum_Body1 = 16974534; // 0x10302c6 - field public static final int TextAppearance_Quantum_Body2 = 16974533; // 0x10302c5 - field public static final int TextAppearance_Quantum_Button = 16974537; // 0x10302c9 - field public static final int TextAppearance_Quantum_Caption = 16974535; // 0x10302c7 + field public static final int TextAppearance_Quantum_Body1 = 16974538; // 0x10302ca + field public static final int TextAppearance_Quantum_Body2 = 16974537; // 0x10302c9 + field public static final int TextAppearance_Quantum_Button = 16974541; // 0x10302cd + field public static final int TextAppearance_Quantum_Caption = 16974539; // 0x10302cb field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974347; // 0x103020b - field public static final int TextAppearance_Quantum_Display1 = 16974529; // 0x10302c1 - field public static final int TextAppearance_Quantum_Display2 = 16974528; // 0x10302c0 - field public static final int TextAppearance_Quantum_Display3 = 16974527; // 0x10302bf - field public static final int TextAppearance_Quantum_Display4 = 16974526; // 0x10302be - field public static final int TextAppearance_Quantum_Headline = 16974530; // 0x10302c2 + field public static final int TextAppearance_Quantum_Display1 = 16974533; // 0x10302c5 + field public static final int TextAppearance_Quantum_Display2 = 16974532; // 0x10302c4 + field public static final int TextAppearance_Quantum_Display3 = 16974531; // 0x10302c3 + field public static final int TextAppearance_Quantum_Display4 = 16974530; // 0x10302c2 + field public static final int TextAppearance_Quantum_Headline = 16974534; // 0x10302c6 field public static final int TextAppearance_Quantum_Inverse = 16974348; // 0x103020c field public static final int TextAppearance_Quantum_Large = 16974349; // 0x103020d field public static final int TextAppearance_Quantum_Large_Inverse = 16974350; // 0x103020e field public static final int TextAppearance_Quantum_Medium = 16974351; // 0x103020f field public static final int TextAppearance_Quantum_Medium_Inverse = 16974352; // 0x1030210 - field public static final int TextAppearance_Quantum_Menu = 16974536; // 0x10302c8 + field public static final int TextAppearance_Quantum_Menu = 16974540; // 0x10302cc field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974353; // 0x1030211 field public static final int TextAppearance_Quantum_SearchResult_Title = 16974354; // 0x1030212 field public static final int TextAppearance_Quantum_Small = 16974355; // 0x1030213 field public static final int TextAppearance_Quantum_Small_Inverse = 16974356; // 0x1030214 - field public static final int TextAppearance_Quantum_Subhead = 16974532; // 0x10302c4 - field public static final int TextAppearance_Quantum_Title = 16974531; // 0x10302c3 + field public static final int TextAppearance_Quantum_Subhead = 16974536; // 0x10302c8 + field public static final int TextAppearance_Quantum_Title = 16974535; // 0x10302c7 field public static final int TextAppearance_Quantum_Widget = 16974358; // 0x1030216 field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974359; // 0x1030217 field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974360; // 0x1030218 - field public static final int TextAppearance_Quantum_Widget_ActionBar_Title = 16974361; // 0x1030219 - field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle = 16974362; // 0x103021a - field public static final int TextAppearance_Quantum_Widget_ActionMode_Title = 16974363; // 0x103021b - field public static final int TextAppearance_Quantum_Widget_Button = 16974364; // 0x103021c - field public static final int TextAppearance_Quantum_Widget_DropDownHint = 16974365; // 0x103021d - field public static final int TextAppearance_Quantum_Widget_DropDownItem = 16974366; // 0x103021e - field public static final int TextAppearance_Quantum_Widget_EditText = 16974367; // 0x103021f - field public static final int TextAppearance_Quantum_Widget_IconMenu_Item = 16974368; // 0x1030220 - field public static final int TextAppearance_Quantum_Widget_PopupMenu = 16974369; // 0x1030221 - field public static final int TextAppearance_Quantum_Widget_PopupMenu_Large = 16974370; // 0x1030222 - field public static final int TextAppearance_Quantum_Widget_PopupMenu_Small = 16974371; // 0x1030223 - field public static final int TextAppearance_Quantum_Widget_TabWidget = 16974372; // 0x1030224 - field public static final int TextAppearance_Quantum_Widget_TextView = 16974373; // 0x1030225 - field public static final int TextAppearance_Quantum_Widget_TextView_PopupMenu = 16974374; // 0x1030226 - field public static final int TextAppearance_Quantum_Widget_TextView_SpinnerItem = 16974375; // 0x1030227 + field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle_Inverse = 16974361; // 0x1030219 + field public static final int TextAppearance_Quantum_Widget_ActionBar_Title = 16974362; // 0x103021a + field public static final int TextAppearance_Quantum_Widget_ActionBar_Title_Inverse = 16974363; // 0x103021b + field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle = 16974364; // 0x103021c + field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle_Inverse = 16974365; // 0x103021d + field public static final int TextAppearance_Quantum_Widget_ActionMode_Title = 16974366; // 0x103021e + field public static final int TextAppearance_Quantum_Widget_ActionMode_Title_Inverse = 16974367; // 0x103021f + field public static final int TextAppearance_Quantum_Widget_Button = 16974368; // 0x1030220 + field public static final int TextAppearance_Quantum_Widget_DropDownHint = 16974369; // 0x1030221 + field public static final int TextAppearance_Quantum_Widget_DropDownItem = 16974370; // 0x1030222 + field public static final int TextAppearance_Quantum_Widget_EditText = 16974371; // 0x1030223 + field public static final int TextAppearance_Quantum_Widget_IconMenu_Item = 16974372; // 0x1030224 + field public static final int TextAppearance_Quantum_Widget_PopupMenu = 16974373; // 0x1030225 + field public static final int TextAppearance_Quantum_Widget_PopupMenu_Large = 16974374; // 0x1030226 + field public static final int TextAppearance_Quantum_Widget_PopupMenu_Small = 16974375; // 0x1030227 + field public static final int TextAppearance_Quantum_Widget_TabWidget = 16974376; // 0x1030228 + field public static final int TextAppearance_Quantum_Widget_TextView = 16974377; // 0x1030229 + field public static final int TextAppearance_Quantum_Widget_TextView_PopupMenu = 16974378; // 0x103022a + field public static final int TextAppearance_Quantum_Widget_TextView_SpinnerItem = 16974379; // 0x103022b field public static final int TextAppearance_Quantum_WindowTitle = 16974357; // 0x1030215 field public static final int TextAppearance_Small = 16973894; // 0x1030046 field public static final int TextAppearance_Small_Inverse = 16973895; // 0x1030047 @@ -1956,34 +1961,34 @@ package android { field public static final int Theme_NoTitleBar_Fullscreen = 16973831; // 0x1030007 field public static final int Theme_NoTitleBar_OverlayActionModes = 16973930; // 0x103006a field public static final int Theme_Panel = 16973913; // 0x1030059 - field public static final int Theme_Quantum = 16974376; // 0x1030228 - field public static final int Theme_Quantum_Dialog = 16974377; // 0x1030229 - field public static final int Theme_Quantum_DialogWhenLarge = 16974381; // 0x103022d - field public static final int Theme_Quantum_DialogWhenLarge_NoActionBar = 16974382; // 0x103022e - field public static final int Theme_Quantum_Dialog_MinWidth = 16974378; // 0x103022a - field public static final int Theme_Quantum_Dialog_NoActionBar = 16974379; // 0x103022b - field public static final int Theme_Quantum_Dialog_NoActionBar_MinWidth = 16974380; // 0x103022c - field public static final int Theme_Quantum_InputMethod = 16974383; // 0x103022f - field public static final int Theme_Quantum_Light = 16974391; // 0x1030237 - field public static final int Theme_Quantum_Light_DarkActionBar = 16974392; // 0x1030238 - field public static final int Theme_Quantum_Light_Dialog = 16974393; // 0x1030239 - field public static final int Theme_Quantum_Light_DialogWhenLarge = 16974397; // 0x103023d - field public static final int Theme_Quantum_Light_DialogWhenLarge_NoActionBar = 16974398; // 0x103023e - field public static final int Theme_Quantum_Light_Dialog_MinWidth = 16974394; // 0x103023a - field public static final int Theme_Quantum_Light_Dialog_NoActionBar = 16974395; // 0x103023b - field public static final int Theme_Quantum_Light_Dialog_NoActionBar_MinWidth = 16974396; // 0x103023c - field public static final int Theme_Quantum_Light_NoActionBar = 16974399; // 0x103023f - field public static final int Theme_Quantum_Light_NoActionBar_Fullscreen = 16974400; // 0x1030240 - field public static final int Theme_Quantum_Light_NoActionBar_Overscan = 16974401; // 0x1030241 - field public static final int Theme_Quantum_Light_NoActionBar_TranslucentDecor = 16974402; // 0x1030242 - field public static final int Theme_Quantum_Light_Panel = 16974403; // 0x1030243 - field public static final int Theme_Quantum_NoActionBar = 16974384; // 0x1030230 - field public static final int Theme_Quantum_NoActionBar_Fullscreen = 16974385; // 0x1030231 - field public static final int Theme_Quantum_NoActionBar_Overscan = 16974386; // 0x1030232 - field public static final int Theme_Quantum_NoActionBar_TranslucentDecor = 16974387; // 0x1030233 - field public static final int Theme_Quantum_Panel = 16974388; // 0x1030234 - field public static final int Theme_Quantum_Wallpaper = 16974389; // 0x1030235 - field public static final int Theme_Quantum_Wallpaper_NoTitleBar = 16974390; // 0x1030236 + field public static final int Theme_Quantum = 16974380; // 0x103022c + field public static final int Theme_Quantum_Dialog = 16974381; // 0x103022d + field public static final int Theme_Quantum_DialogWhenLarge = 16974385; // 0x1030231 + field public static final int Theme_Quantum_DialogWhenLarge_NoActionBar = 16974386; // 0x1030232 + field public static final int Theme_Quantum_Dialog_MinWidth = 16974382; // 0x103022e + field public static final int Theme_Quantum_Dialog_NoActionBar = 16974383; // 0x103022f + field public static final int Theme_Quantum_Dialog_NoActionBar_MinWidth = 16974384; // 0x1030230 + field public static final int Theme_Quantum_InputMethod = 16974387; // 0x1030233 + field public static final int Theme_Quantum_Light = 16974395; // 0x103023b + field public static final int Theme_Quantum_Light_DarkActionBar = 16974396; // 0x103023c + field public static final int Theme_Quantum_Light_Dialog = 16974397; // 0x103023d + field public static final int Theme_Quantum_Light_DialogWhenLarge = 16974401; // 0x1030241 + field public static final int Theme_Quantum_Light_DialogWhenLarge_NoActionBar = 16974402; // 0x1030242 + field public static final int Theme_Quantum_Light_Dialog_MinWidth = 16974398; // 0x103023e + field public static final int Theme_Quantum_Light_Dialog_NoActionBar = 16974399; // 0x103023f + field public static final int Theme_Quantum_Light_Dialog_NoActionBar_MinWidth = 16974400; // 0x1030240 + field public static final int Theme_Quantum_Light_NoActionBar = 16974403; // 0x1030243 + field public static final int Theme_Quantum_Light_NoActionBar_Fullscreen = 16974404; // 0x1030244 + field public static final int Theme_Quantum_Light_NoActionBar_Overscan = 16974405; // 0x1030245 + field public static final int Theme_Quantum_Light_NoActionBar_TranslucentDecor = 16974406; // 0x1030246 + field public static final int Theme_Quantum_Light_Panel = 16974407; // 0x1030247 + field public static final int Theme_Quantum_NoActionBar = 16974388; // 0x1030234 + field public static final int Theme_Quantum_NoActionBar_Fullscreen = 16974389; // 0x1030235 + field public static final int Theme_Quantum_NoActionBar_Overscan = 16974390; // 0x1030236 + field public static final int Theme_Quantum_NoActionBar_TranslucentDecor = 16974391; // 0x1030237 + field public static final int Theme_Quantum_Panel = 16974392; // 0x1030238 + field public static final int Theme_Quantum_Wallpaper = 16974393; // 0x1030239 + field public static final int Theme_Quantum_Wallpaper_NoTitleBar = 16974394; // 0x103023a field public static final int Theme_Translucent = 16973839; // 0x103000f field public static final int Theme_Translucent_NoTitleBar = 16973840; // 0x1030010 field public static final int Theme_Translucent_NoTitleBar_Fullscreen = 16973841; // 0x1030011 @@ -2187,7 +2192,7 @@ package android { field public static final int Widget_Holo_Light_ActionMode_Inverse = 16974119; // 0x1030127 field public static final int Widget_Holo_Light_AutoCompleteTextView = 16974011; // 0x10300bb field public static final int Widget_Holo_Light_Button = 16974006; // 0x10300b6 - field public static final int Widget_Holo_Light_Button_Borderless = 16974538; // 0x10302ca + field public static final int Widget_Holo_Light_Button_Borderless = 16974542; // 0x10302ce field public static final int Widget_Holo_Light_Button_Borderless_Small = 16974107; // 0x103011b field public static final int Widget_Holo_Light_Button_Inset = 16974008; // 0x10300b8 field public static final int Widget_Holo_Light_Button_Small = 16974007; // 0x10300b7 @@ -2272,128 +2277,128 @@ package android { field public static final int Widget_ProgressBar_Large_Inverse = 16973916; // 0x103005c field public static final int Widget_ProgressBar_Small = 16973854; // 0x103001e field public static final int Widget_ProgressBar_Small_Inverse = 16973917; // 0x103005d - field public static final int Widget_Quantum = 16974404; // 0x1030244 - field public static final int Widget_Quantum_ActionBar = 16974405; // 0x1030245 - field public static final int Widget_Quantum_ActionBar_Solid = 16974406; // 0x1030246 - field public static final int Widget_Quantum_ActionBar_TabBar = 16974407; // 0x1030247 - field public static final int Widget_Quantum_ActionBar_TabText = 16974408; // 0x1030248 - field public static final int Widget_Quantum_ActionBar_TabView = 16974409; // 0x1030249 - field public static final int Widget_Quantum_ActionButton = 16974410; // 0x103024a - field public static final int Widget_Quantum_ActionButton_CloseMode = 16974411; // 0x103024b - field public static final int Widget_Quantum_ActionButton_Overflow = 16974412; // 0x103024c - field public static final int Widget_Quantum_ActionButton_TextButton = 16974413; // 0x103024d - field public static final int Widget_Quantum_ActionMode = 16974414; // 0x103024e - field public static final int Widget_Quantum_AutoCompleteTextView = 16974415; // 0x103024f - field public static final int Widget_Quantum_Button = 16974416; // 0x1030250 - field public static final int Widget_Quantum_ButtonBar = 16974422; // 0x1030256 - field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974423; // 0x1030257 - field public static final int Widget_Quantum_Button_Borderless = 16974417; // 0x1030251 - field public static final int Widget_Quantum_Button_Borderless_Small = 16974418; // 0x1030252 - field public static final int Widget_Quantum_Button_Inset = 16974419; // 0x1030253 - field public static final int Widget_Quantum_Button_Paper = 16974522; // 0x10302ba - field public static final int Widget_Quantum_Button_Paper_Color = 16974523; // 0x10302bb - field public static final int Widget_Quantum_Button_Small = 16974420; // 0x1030254 - field public static final int Widget_Quantum_Button_Toggle = 16974421; // 0x1030255 - field public static final int Widget_Quantum_CalendarView = 16974424; // 0x1030258 - field public static final int Widget_Quantum_CheckedTextView = 16974425; // 0x1030259 - field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974426; // 0x103025a - field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974427; // 0x103025b - field public static final int Widget_Quantum_CompoundButton_Star = 16974428; // 0x103025c - field public static final int Widget_Quantum_DatePicker = 16974429; // 0x103025d - field public static final int Widget_Quantum_DropDownItem = 16974430; // 0x103025e - field public static final int Widget_Quantum_DropDownItem_Spinner = 16974431; // 0x103025f - field public static final int Widget_Quantum_EditText = 16974432; // 0x1030260 - field public static final int Widget_Quantum_ExpandableListView = 16974433; // 0x1030261 - field public static final int Widget_Quantum_FastScroll = 16974434; // 0x1030262 - field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974435; // 0x1030263 - field public static final int Widget_Quantum_GridView = 16974436; // 0x1030264 - field public static final int Widget_Quantum_HorizontalScrollView = 16974437; // 0x1030265 - field public static final int Widget_Quantum_ImageButton = 16974438; // 0x1030266 - field public static final int Widget_Quantum_Light = 16974463; // 0x103027f - field public static final int Widget_Quantum_Light_ActionBar = 16974464; // 0x1030280 - field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974465; // 0x1030281 - field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974466; // 0x1030282 - field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974467; // 0x1030283 - field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974468; // 0x1030284 - field public static final int Widget_Quantum_Light_ActionButton = 16974469; // 0x1030285 - field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974470; // 0x1030286 - field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974471; // 0x1030287 - field public static final int Widget_Quantum_Light_ActionMode = 16974472; // 0x1030288 - field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974473; // 0x1030289 - field public static final int Widget_Quantum_Light_Button = 16974474; // 0x103028a - field public static final int Widget_Quantum_Light_ButtonBar = 16974479; // 0x103028f - field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974480; // 0x1030290 - field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974475; // 0x103028b - field public static final int Widget_Quantum_Light_Button_Inset = 16974476; // 0x103028c - field public static final int Widget_Quantum_Light_Button_Paper = 16974524; // 0x10302bc - field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974525; // 0x10302bd - field public static final int Widget_Quantum_Light_Button_Small = 16974477; // 0x103028d - field public static final int Widget_Quantum_Light_Button_Toggle = 16974478; // 0x103028e - field public static final int Widget_Quantum_Light_CalendarView = 16974481; // 0x1030291 - field public static final int Widget_Quantum_Light_CheckedTextView = 16974482; // 0x1030292 - field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974483; // 0x1030293 - field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974484; // 0x1030294 - field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974485; // 0x1030295 - field public static final int Widget_Quantum_Light_DropDownItem = 16974486; // 0x1030296 - field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974487; // 0x1030297 - field public static final int Widget_Quantum_Light_EditText = 16974488; // 0x1030298 - field public static final int Widget_Quantum_Light_ExpandableListView = 16974489; // 0x1030299 - field public static final int Widget_Quantum_Light_FastScroll = 16974490; // 0x103029a - field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974491; // 0x103029b - field public static final int Widget_Quantum_Light_GridView = 16974492; // 0x103029c - field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974493; // 0x103029d - field public static final int Widget_Quantum_Light_ImageButton = 16974494; // 0x103029e - field public static final int Widget_Quantum_Light_ListPopupWindow = 16974495; // 0x103029f - field public static final int Widget_Quantum_Light_ListView = 16974496; // 0x10302a0 - field public static final int Widget_Quantum_Light_ListView_DropDown = 16974497; // 0x10302a1 - field public static final int Widget_Quantum_Light_MediaRouteButton = 16974498; // 0x10302a2 - field public static final int Widget_Quantum_Light_PopupMenu = 16974499; // 0x10302a3 - field public static final int Widget_Quantum_Light_PopupWindow = 16974500; // 0x10302a4 - field public static final int Widget_Quantum_Light_ProgressBar = 16974501; // 0x10302a5 - field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974502; // 0x10302a6 - field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974503; // 0x10302a7 - field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974504; // 0x10302a8 - field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974505; // 0x10302a9 - field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974506; // 0x10302aa - field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974507; // 0x10302ab - field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974508; // 0x10302ac - field public static final int Widget_Quantum_Light_RatingBar = 16974509; // 0x10302ad - field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974510; // 0x10302ae - field public static final int Widget_Quantum_Light_RatingBar_Small = 16974511; // 0x10302af - field public static final int Widget_Quantum_Light_ScrollView = 16974512; // 0x10302b0 - field public static final int Widget_Quantum_Light_SeekBar = 16974513; // 0x10302b1 - field public static final int Widget_Quantum_Light_SegmentedButton = 16974514; // 0x10302b2 - field public static final int Widget_Quantum_Light_Spinner = 16974515; // 0x10302b3 - field public static final int Widget_Quantum_Light_Tab = 16974516; // 0x10302b4 - field public static final int Widget_Quantum_Light_TabWidget = 16974517; // 0x10302b5 - field public static final int Widget_Quantum_Light_TextView = 16974518; // 0x10302b6 - field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974519; // 0x10302b7 - field public static final int Widget_Quantum_Light_WebTextView = 16974520; // 0x10302b8 - field public static final int Widget_Quantum_Light_WebView = 16974521; // 0x10302b9 - field public static final int Widget_Quantum_ListPopupWindow = 16974439; // 0x1030267 - field public static final int Widget_Quantum_ListView = 16974440; // 0x1030268 - field public static final int Widget_Quantum_ListView_DropDown = 16974441; // 0x1030269 - field public static final int Widget_Quantum_MediaRouteButton = 16974442; // 0x103026a - field public static final int Widget_Quantum_PopupMenu = 16974443; // 0x103026b - field public static final int Widget_Quantum_PopupWindow = 16974444; // 0x103026c - field public static final int Widget_Quantum_ProgressBar = 16974445; // 0x103026d - field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974446; // 0x103026e - field public static final int Widget_Quantum_ProgressBar_Large = 16974447; // 0x103026f - field public static final int Widget_Quantum_ProgressBar_Small = 16974448; // 0x1030270 - field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974449; // 0x1030271 - field public static final int Widget_Quantum_RatingBar = 16974450; // 0x1030272 - field public static final int Widget_Quantum_RatingBar_Indicator = 16974451; // 0x1030273 - field public static final int Widget_Quantum_RatingBar_Small = 16974452; // 0x1030274 - field public static final int Widget_Quantum_ScrollView = 16974453; // 0x1030275 - field public static final int Widget_Quantum_SeekBar = 16974454; // 0x1030276 - field public static final int Widget_Quantum_SegmentedButton = 16974455; // 0x1030277 - field public static final int Widget_Quantum_Spinner = 16974456; // 0x1030278 - field public static final int Widget_Quantum_Tab = 16974457; // 0x1030279 - field public static final int Widget_Quantum_TabWidget = 16974458; // 0x103027a - field public static final int Widget_Quantum_TextView = 16974459; // 0x103027b - field public static final int Widget_Quantum_TextView_SpinnerItem = 16974460; // 0x103027c - field public static final int Widget_Quantum_WebTextView = 16974461; // 0x103027d - field public static final int Widget_Quantum_WebView = 16974462; // 0x103027e + field public static final int Widget_Quantum = 16974408; // 0x1030248 + field public static final int Widget_Quantum_ActionBar = 16974409; // 0x1030249 + field public static final int Widget_Quantum_ActionBar_Solid = 16974410; // 0x103024a + field public static final int Widget_Quantum_ActionBar_TabBar = 16974411; // 0x103024b + field public static final int Widget_Quantum_ActionBar_TabText = 16974412; // 0x103024c + field public static final int Widget_Quantum_ActionBar_TabView = 16974413; // 0x103024d + field public static final int Widget_Quantum_ActionButton = 16974414; // 0x103024e + field public static final int Widget_Quantum_ActionButton_CloseMode = 16974415; // 0x103024f + field public static final int Widget_Quantum_ActionButton_Overflow = 16974416; // 0x1030250 + field public static final int Widget_Quantum_ActionButton_TextButton = 16974417; // 0x1030251 + field public static final int Widget_Quantum_ActionMode = 16974418; // 0x1030252 + field public static final int Widget_Quantum_AutoCompleteTextView = 16974419; // 0x1030253 + field public static final int Widget_Quantum_Button = 16974420; // 0x1030254 + field public static final int Widget_Quantum_ButtonBar = 16974426; // 0x103025a + field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974427; // 0x103025b + field public static final int Widget_Quantum_Button_Borderless = 16974421; // 0x1030255 + field public static final int Widget_Quantum_Button_Borderless_Small = 16974422; // 0x1030256 + field public static final int Widget_Quantum_Button_Inset = 16974423; // 0x1030257 + field public static final int Widget_Quantum_Button_Paper = 16974526; // 0x10302be + field public static final int Widget_Quantum_Button_Paper_Color = 16974527; // 0x10302bf + field public static final int Widget_Quantum_Button_Small = 16974424; // 0x1030258 + field public static final int Widget_Quantum_Button_Toggle = 16974425; // 0x1030259 + field public static final int Widget_Quantum_CalendarView = 16974428; // 0x103025c + field public static final int Widget_Quantum_CheckedTextView = 16974429; // 0x103025d + field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974430; // 0x103025e + field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974431; // 0x103025f + field public static final int Widget_Quantum_CompoundButton_Star = 16974432; // 0x1030260 + field public static final int Widget_Quantum_DatePicker = 16974433; // 0x1030261 + field public static final int Widget_Quantum_DropDownItem = 16974434; // 0x1030262 + field public static final int Widget_Quantum_DropDownItem_Spinner = 16974435; // 0x1030263 + field public static final int Widget_Quantum_EditText = 16974436; // 0x1030264 + field public static final int Widget_Quantum_ExpandableListView = 16974437; // 0x1030265 + field public static final int Widget_Quantum_FastScroll = 16974438; // 0x1030266 + field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974439; // 0x1030267 + field public static final int Widget_Quantum_GridView = 16974440; // 0x1030268 + field public static final int Widget_Quantum_HorizontalScrollView = 16974441; // 0x1030269 + field public static final int Widget_Quantum_ImageButton = 16974442; // 0x103026a + field public static final int Widget_Quantum_Light = 16974467; // 0x1030283 + field public static final int Widget_Quantum_Light_ActionBar = 16974468; // 0x1030284 + field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974469; // 0x1030285 + field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974470; // 0x1030286 + field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974471; // 0x1030287 + field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974472; // 0x1030288 + field public static final int Widget_Quantum_Light_ActionButton = 16974473; // 0x1030289 + field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974474; // 0x103028a + field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974475; // 0x103028b + field public static final int Widget_Quantum_Light_ActionMode = 16974476; // 0x103028c + field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974477; // 0x103028d + field public static final int Widget_Quantum_Light_Button = 16974478; // 0x103028e + field public static final int Widget_Quantum_Light_ButtonBar = 16974483; // 0x1030293 + field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974484; // 0x1030294 + field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974479; // 0x103028f + field public static final int Widget_Quantum_Light_Button_Inset = 16974480; // 0x1030290 + field public static final int Widget_Quantum_Light_Button_Paper = 16974528; // 0x10302c0 + field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974529; // 0x10302c1 + field public static final int Widget_Quantum_Light_Button_Small = 16974481; // 0x1030291 + field public static final int Widget_Quantum_Light_Button_Toggle = 16974482; // 0x1030292 + field public static final int Widget_Quantum_Light_CalendarView = 16974485; // 0x1030295 + field public static final int Widget_Quantum_Light_CheckedTextView = 16974486; // 0x1030296 + field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974487; // 0x1030297 + field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974488; // 0x1030298 + field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974489; // 0x1030299 + field public static final int Widget_Quantum_Light_DropDownItem = 16974490; // 0x103029a + field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974491; // 0x103029b + field public static final int Widget_Quantum_Light_EditText = 16974492; // 0x103029c + field public static final int Widget_Quantum_Light_ExpandableListView = 16974493; // 0x103029d + field public static final int Widget_Quantum_Light_FastScroll = 16974494; // 0x103029e + field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974495; // 0x103029f + field public static final int Widget_Quantum_Light_GridView = 16974496; // 0x10302a0 + field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974497; // 0x10302a1 + field public static final int Widget_Quantum_Light_ImageButton = 16974498; // 0x10302a2 + field public static final int Widget_Quantum_Light_ListPopupWindow = 16974499; // 0x10302a3 + field public static final int Widget_Quantum_Light_ListView = 16974500; // 0x10302a4 + field public static final int Widget_Quantum_Light_ListView_DropDown = 16974501; // 0x10302a5 + field public static final int Widget_Quantum_Light_MediaRouteButton = 16974502; // 0x10302a6 + field public static final int Widget_Quantum_Light_PopupMenu = 16974503; // 0x10302a7 + field public static final int Widget_Quantum_Light_PopupWindow = 16974504; // 0x10302a8 + field public static final int Widget_Quantum_Light_ProgressBar = 16974505; // 0x10302a9 + field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974506; // 0x10302aa + field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974507; // 0x10302ab + field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974508; // 0x10302ac + field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974509; // 0x10302ad + field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974510; // 0x10302ae + field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974511; // 0x10302af + field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974512; // 0x10302b0 + field public static final int Widget_Quantum_Light_RatingBar = 16974513; // 0x10302b1 + field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974514; // 0x10302b2 + field public static final int Widget_Quantum_Light_RatingBar_Small = 16974515; // 0x10302b3 + field public static final int Widget_Quantum_Light_ScrollView = 16974516; // 0x10302b4 + field public static final int Widget_Quantum_Light_SeekBar = 16974517; // 0x10302b5 + field public static final int Widget_Quantum_Light_SegmentedButton = 16974518; // 0x10302b6 + field public static final int Widget_Quantum_Light_Spinner = 16974519; // 0x10302b7 + field public static final int Widget_Quantum_Light_Tab = 16974520; // 0x10302b8 + field public static final int Widget_Quantum_Light_TabWidget = 16974521; // 0x10302b9 + field public static final int Widget_Quantum_Light_TextView = 16974522; // 0x10302ba + field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974523; // 0x10302bb + field public static final int Widget_Quantum_Light_WebTextView = 16974524; // 0x10302bc + field public static final int Widget_Quantum_Light_WebView = 16974525; // 0x10302bd + field public static final int Widget_Quantum_ListPopupWindow = 16974443; // 0x103026b + field public static final int Widget_Quantum_ListView = 16974444; // 0x103026c + field public static final int Widget_Quantum_ListView_DropDown = 16974445; // 0x103026d + field public static final int Widget_Quantum_MediaRouteButton = 16974446; // 0x103026e + field public static final int Widget_Quantum_PopupMenu = 16974447; // 0x103026f + field public static final int Widget_Quantum_PopupWindow = 16974448; // 0x1030270 + field public static final int Widget_Quantum_ProgressBar = 16974449; // 0x1030271 + field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974450; // 0x1030272 + field public static final int Widget_Quantum_ProgressBar_Large = 16974451; // 0x1030273 + field public static final int Widget_Quantum_ProgressBar_Small = 16974452; // 0x1030274 + field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974453; // 0x1030275 + field public static final int Widget_Quantum_RatingBar = 16974454; // 0x1030276 + field public static final int Widget_Quantum_RatingBar_Indicator = 16974455; // 0x1030277 + field public static final int Widget_Quantum_RatingBar_Small = 16974456; // 0x1030278 + field public static final int Widget_Quantum_ScrollView = 16974457; // 0x1030279 + field public static final int Widget_Quantum_SeekBar = 16974458; // 0x103027a + field public static final int Widget_Quantum_SegmentedButton = 16974459; // 0x103027b + field public static final int Widget_Quantum_Spinner = 16974460; // 0x103027c + field public static final int Widget_Quantum_Tab = 16974461; // 0x103027d + field public static final int Widget_Quantum_TabWidget = 16974462; // 0x103027e + field public static final int Widget_Quantum_TextView = 16974463; // 0x103027f + field public static final int Widget_Quantum_TextView_SpinnerItem = 16974464; // 0x1030280 + field public static final int Widget_Quantum_WebTextView = 16974465; // 0x1030281 + field public static final int Widget_Quantum_WebView = 16974466; // 0x1030282 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 @@ -3258,6 +3263,7 @@ package android.app { method public void reportFullyDrawn(); method public final boolean requestWindowFeature(int); method public final void runOnUiThread(java.lang.Runnable); + method public void setActivityLabelAndIcon(java.lang.CharSequence, android.graphics.Bitmap); method public void setContentTransitionManager(android.transition.TransitionManager); method public void setContentView(int); method public void setContentView(android.view.View); @@ -3274,8 +3280,6 @@ package android.app { method public final void setProgressBarIndeterminate(boolean); method public final void setProgressBarIndeterminateVisibility(boolean); method public final void setProgressBarVisibility(boolean); - method public void setRecentsIcon(android.graphics.Bitmap); - method public void setRecentsLabel(java.lang.CharSequence); method public void setRequestedOrientation(int); method public final void setResult(int); method public final void setResult(int, android.content.Intent); @@ -12083,11 +12087,16 @@ package android.hardware.hdmi { field public static final int MESSAGE_VENDOR_COMMAND_WITH_ID = 160; // 0xa0 field public static final int MESSAGE_VENDOR_REMOTE_BUTTON_DOWN = 138; // 0x8a field public static final int MESSAGE_VENDOR_REMOTE_BUTTON_UP = 139; // 0x8b + field public static final int POWER_STATUS_ON = 0; // 0x0 + field public static final int POWER_STATUS_STANDBY = 1; // 0x1 + field public static final int POWER_STATUS_UNKNOWN = -1; // 0xffffffff + field public static final int POWER_TRANSIENT_TO_ON = 2; // 0x2 + field public static final int POWER_TRANSIENT_TO_STANDBY = 3; // 0x3 } public final class HdmiCecClient { + method public boolean isTvOn(); method public void sendActiveSource(); - method public void sendGiveDevicePowerStatus(int); method public void sendImageViewOn(); method public void sendInactiveSource(); method public void sendTextViewOn(); diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp index 8d2b739..bdbb08c 100644 --- a/cmds/app_process/app_main.cpp +++ b/cmds/app_process/app_main.cpp @@ -30,8 +30,9 @@ void app_usage() class AppRuntime : public AndroidRuntime { public: - AppRuntime() - : mParentDir(NULL) + AppRuntime(char* argBlockStart, const size_t argBlockLength) + : AndroidRuntime(argBlockStart, argBlockLength) + , mParentDir(NULL) , mClassName(NULL) , mClass(NULL) , mArgC(0) @@ -125,29 +126,30 @@ public: using namespace android; -/* - * sets argv0 to as much of newArgv0 as will fit - */ -static void setArgv0(const char *argv0, const char *newArgv0) -{ - strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0)); +static size_t computeArgBlockSize(int argc, char* const argv[]) { + // TODO: This assumes that all arguments are allocated in + // contiguous memory. There isn't any documented guarantee + // that this is the case, but this is how the kernel does it + // (see fs/exec.c). + // + // Also note that this is a constant for "normal" android apps. + // Since they're forked from zygote, the size of their command line + // is the size of the zygote command line. + // + // We change the process name of the process by over-writing + // the start of the argument block (argv[0]) with the new name of + // the process, so we'd mysteriously start getting truncated process + // names if the zygote command line decreases in size. + uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]); + uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]); + end += strlen(argv[argc - 1]); + + return (end - start); } int main(int argc, char* const argv[]) { - // These are global variables in ProcessState.cpp - mArgC = argc; - mArgV = argv; - - mArgLen = 0; - for (int i=0; i<argc; i++) { - mArgLen += strlen(argv[i]) + 1; - } - mArgLen--; - - AppRuntime runtime; - const char* argv0 = argv[0]; - + AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] argc--; @@ -184,7 +186,7 @@ int main(int argc, char* const argv[]) } if (niceName && *niceName) { - setArgv0(argv0, niceName); + runtime.setArgv0(niceName); set_process_name(niceName); } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index e38bbb3..23caccc 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -4701,42 +4701,33 @@ public class Activity extends ContextThemeWrapper } /** - * Set a label to be used in the Recents task display. The activities of a task are traversed - * in order from the topmost activity to the bottommost. As soon as one activity returns a - * non-null Recents label the traversal is ended and that value will be used in - * {@link ActivityManager.RecentTaskInfo#activityLabel} + * Set a label and icon to be used in the Recents task display. When {@link + * ActivityManager#getRecentTasks} is called, the activities of each task are + * traversed in order from the topmost activity to the bottommost. As soon as one activity is + * found with either a non-null label or a non-null icon set by this call the traversal is + * ended. For each task those values will be returned in {@link + * ActivityManager.RecentTaskInfo#activityLabel} and {@link + * ActivityManager.RecentTaskInfo#activityIcon}. The {link Intent} for the activity that set + * activityLabel and activityIcon will be returned in {@link + * ActivityManager.RecentTaskInfo#activityIntent} * * @see ActivityManager#getRecentTasks + * @see ActivityManager.RecentTaskInfo * - * @param recentsLabel The label to use in the RecentTaskInfo. + * @param activityLabel The label to use in the RecentTaskInfo. + * @param activityIcon The Bitmap to use in the RecentTaskInfo. */ - public void setRecentsLabel(CharSequence recentsLabel) { - try { - ActivityManagerNative.getDefault().setRecentsLabel(mToken, recentsLabel); - } catch (RemoteException e) { - } - } - - /** - * Set an icon to be used in the Recents task display. The activities of a task are traversed - * in order from the topmost activity to the bottommost. As soon as one activity returns a - * non-null Recents icon the traversal is ended and that value will be used in - * {@link ActivityManager.RecentTaskInfo#activityIcon}. - * - * @see ActivityManager#getRecentTasks - * - * @param recentsIcon The Bitmap to use in the RecentTaskInfo. - */ - public void setRecentsIcon(Bitmap recentsIcon) { + public void setActivityLabelAndIcon(CharSequence activityLabel, Bitmap activityIcon) { final Bitmap scaledIcon; - if (recentsIcon != null) { + if (activityIcon != null) { final int size = ActivityManager.getLauncherLargeIconSizeInner(this); - scaledIcon = Bitmap.createScaledBitmap(recentsIcon, size, size, true); + scaledIcon = Bitmap.createScaledBitmap(activityIcon, size, size, true); } else { scaledIcon = null; } try { - ActivityManagerNative.getDefault().setRecentsIcon(mToken, scaledIcon); + ActivityManagerNative.getDefault().setActivityLabelAndIcon(mToken, activityLabel, + scaledIcon); } catch (RemoteException e) { } } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 9d6a340..c027e99 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -516,14 +516,14 @@ public class ActivityManager { public int userId; /** - * The label of the highest activity in the task stack to have set a label - * {@link Activity#setRecentsLabel}. + * The label of the highest activity in the task stack to have set a label using + * {@link Activity#setActivityLabelAndIcon(CharSequence, android.graphics.Bitmap)}. */ public CharSequence activityLabel; /** * The Bitmap icon of the highest activity in the task stack to set a Bitmap using - * {@link Activity#setRecentsIcon}. + * {@link Activity#setActivityLabelAndIcon(CharSequence, android.graphics.Bitmap)}. */ public Bitmap activityIcon; @@ -563,11 +563,7 @@ public class ActivityManager { public void readFromParcel(Parcel source) { id = source.readInt(); persistentId = source.readInt(); - if (source.readInt() != 0) { - baseIntent = Intent.CREATOR.createFromParcel(source); - } else { - baseIntent = null; - } + baseIntent = source.readInt() > 0 ? Intent.CREATOR.createFromParcel(source) : null; origActivity = ComponentName.readFromParcel(source); description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); activityLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 707a038..a37a35a 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2129,21 +2129,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } - case SET_RECENTS_LABEL_TRANSACTION: { + case SET_ACTIVITY_LABEL_ICON_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); - CharSequence recentsLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data); - setRecentsLabel(token, recentsLabel); - reply.writeNoException(); - return true; - } - - case SET_RECENTS_ICON_TRANSACTION: { - data.enforceInterface(IActivityManager.descriptor); - IBinder token = data.readStrongBinder(); - Bitmap recentsIcon = data.readInt() != 0 + CharSequence activityLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data); + Bitmap activityIcon = data.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(data) : null; - setRecentsIcon(token, recentsIcon); + setActivityLabelAndIcon(token, activityLabel, activityIcon); reply.writeNoException(); return true; } @@ -4918,32 +4910,22 @@ class ActivityManagerProxy implements IActivityManager return isInLockTaskMode; } - public void setRecentsLabel(IBinder token, CharSequence recentsLabel) throws RemoteException - { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - data.writeInterfaceToken(IActivityManager.descriptor); - data.writeStrongBinder(token); - TextUtils.writeToParcel(recentsLabel, data, 0); - mRemote.transact(SET_RECENTS_LABEL_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); - reply.readException(); - data.recycle(); - reply.recycle(); - } - - public void setRecentsIcon(IBinder token, Bitmap recentsBitmap) throws RemoteException + @Override + public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel, + Bitmap activityIcon) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); - if (recentsBitmap != null) { + TextUtils.writeToParcel(activityLabel, data, 0); + if (activityIcon != null) { data.writeInt(1); - recentsBitmap.writeToParcel(data, 0); + activityIcon.writeToParcel(data, 0); } else { data.writeInt(0); } - mRemote.transact(SET_RECENTS_ICON_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); + mRemote.transact(SET_ACTIVITY_LABEL_ICON_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); reply.readException(); data.recycle(); reply.recycle(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index d1f94f0..7149ab9 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -468,7 +468,8 @@ class ContextImpl extends Context { outerContext.getApplicationInfo().targetSdkVersion, com.android.internal.R.style.Theme_Dialog, com.android.internal.R.style.Theme_Holo_Dialog, - com.android.internal.R.style.Theme_DeviceDefault_Dialog)), + com.android.internal.R.style.Theme_DeviceDefault_Dialog, + com.android.internal.R.style.Theme_DeviceDefault_Light_Dialog)), ctx.mMainThread.getHandler()); }}); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 3b56839..f7416d6 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -437,10 +437,8 @@ public interface IActivityManager extends IInterface { public boolean isInLockTaskMode() throws RemoteException; /** @hide */ - public void setRecentsLabel(IBinder token, CharSequence recentsLabel) throws RemoteException; - - /** @hide */ - public void setRecentsIcon(IBinder token, Bitmap recentsBitmap) throws RemoteException; + public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel, + Bitmap activityBitmap) throws RemoteException; /* * Private non-Binder interfaces @@ -741,6 +739,5 @@ public interface IActivityManager extends IInterface { int START_LOCK_TASK_BY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+214; int STOP_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+215; int IS_IN_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+216; - int SET_RECENTS_LABEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217; - int SET_RECENTS_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+218; + int SET_ACTIVITY_LABEL_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217; } diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 40275d8..9916476 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -189,6 +189,13 @@ public class ActivityInfo extends ComponentInfo */ public static final int FLAG_IMMERSIVE = 0x0800; /** + * Bit in {@link #flags} indicating that this activity is to be persisted across + * reboots for display in the Recents list. + * {@link android.R.attr#persistable} + * @hide + */ + public static final int FLAG_PERSISTABLE = 0x1000; + /** * @hide Bit in {@link #flags}: If set, this component will only be seen * by the primary user. Only works with broadcast receivers. Set from the * {@link android.R.attr#primaryUserOnly} attribute. diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index a89c507..4b5616f 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -57,7 +57,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.jar.JarEntry; import java.util.jar.StrictJarFile; import java.util.zip.ZipEntry; @@ -2448,6 +2447,11 @@ public class PackageParser { a.info.flags |= ActivityInfo.FLAG_IMMERSIVE; } + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_persistable, false)) { + a.info.flags |= ActivityInfo.FLAG_PERSISTABLE; + } + if (!receiver) { if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated, diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 1955be3..d6eafc6 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -135,17 +135,31 @@ public class Resources { sPreloadedDrawables[1] = new LongSparseArray<ConstantState>(); } - /** @hide */ + /** + * Returns the most appropriate default theme for the specified target SDK version. + * <ul> + * <li>Below API 11: Gingerbread + * <li>APIs 11 thru 14: Holo + * <li>APIs 14 thru XX: Device default dark + * <li>API XX and above: Device default light with dark action bar + * </ul> + * + * @param curTheme The current theme, or 0 if not specified. + * @param targetSdkVersion The target SDK version. + * @return A theme resource identifier + * @hide + */ public static int selectDefaultTheme(int curTheme, int targetSdkVersion) { return selectSystemTheme(curTheme, targetSdkVersion, com.android.internal.R.style.Theme, com.android.internal.R.style.Theme_Holo, - com.android.internal.R.style.Theme_DeviceDefault); + com.android.internal.R.style.Theme_DeviceDefault, + com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar); } - + /** @hide */ - public static int selectSystemTheme(int curTheme, int targetSdkVersion, - int orig, int holo, int deviceDefault) { + public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo, + int dark, int deviceDefault) { if (curTheme != 0) { return curTheme; } @@ -155,9 +169,12 @@ public class Resources { if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { return holo; } + if (targetSdkVersion < Build.VERSION_CODES.CUR_DEVELOPMENT) { + return dark; + } return deviceDefault; } - + /** * This exception is thrown by the resource APIs when a requested resource * can not be found. diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java index 38d9de4..8578a32 100644 --- a/core/java/android/hardware/hdmi/HdmiCec.java +++ b/core/java/android/hardware/hdmi/HdmiCec.java @@ -160,6 +160,12 @@ public final class HdmiCec { public static final int MESSAGE_SET_EXTERNAL_TIMER = 0xA2; public static final int MESSAGE_ABORT = 0xFF; + public static final int POWER_STATUS_UNKNOWN = -1; + public static final int POWER_STATUS_ON = 0; + public static final int POWER_STATUS_STANDBY = 1; + public static final int POWER_TRANSIENT_TO_ON = 2; + public static final int POWER_TRANSIENT_TO_STANDBY = 3; + private static final int[] ADDRESS_TO_TYPE = { DEVICE_TV, // ADDR_TV DEVICE_RECORDER, // ADDR_RECORDER_1 diff --git a/core/java/android/hardware/hdmi/HdmiCecClient.java b/core/java/android/hardware/hdmi/HdmiCecClient.java index d7f4a72..1f382e6 100644 --- a/core/java/android/hardware/hdmi/HdmiCecClient.java +++ b/core/java/android/hardware/hdmi/HdmiCecClient.java @@ -110,16 +110,20 @@ public final class HdmiCecClient { } /** - * Send <GiveDevicePowerStatus> message. + * Returns true if the TV or attached display is powered on. + * <p> + * The result of this method is only meaningful on playback devices (where the device + * type is {@link HdmiCec#DEVICE_PLAYBACK}). + * </p> * - * @param address logical address of the device to send the message to, such as - * {@link HdmiCec#ADDR_TV}. + * @return true if TV is on; otherwise false. */ - public void sendGiveDevicePowerStatus(int address) { + public boolean isTvOn() { try { - mService.sendGiveDevicePowerStatus(mBinder, address); + return mService.isTvOn(mBinder); } catch (RemoteException e) { - Log.e(TAG, "sendGiveDevicePowerStatus threw exception ", e); + Log.e(TAG, "isTvOn threw exception ", e); } + return false; } } diff --git a/core/java/android/hardware/hdmi/HdmiCecManager.java b/core/java/android/hardware/hdmi/HdmiCecManager.java index 575785d..10b058c 100644 --- a/core/java/android/hardware/hdmi/HdmiCecManager.java +++ b/core/java/android/hardware/hdmi/HdmiCecManager.java @@ -45,6 +45,9 @@ public final class HdmiCecManager { * @return {@link HdmiCecClient} instance. {@code null} on failure. */ public HdmiCecClient getClient(int type, HdmiCecClient.Listener listener) { + if (mService == null) { + return null; + } try { IBinder b = mService.allocateLogicalDevice(type, getListenerWrapper(listener)); return HdmiCecClient.create(mService, b); diff --git a/core/java/android/hardware/hdmi/IHdmiCecService.aidl b/core/java/android/hardware/hdmi/IHdmiCecService.aidl index 6fefcf8..b5df131 100644 --- a/core/java/android/hardware/hdmi/IHdmiCecService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiCecService.aidl @@ -29,12 +29,11 @@ import android.os.IBinder; interface IHdmiCecService { IBinder allocateLogicalDevice(int type, IHdmiCecListener listener); void removeServiceListener(IBinder b, IHdmiCecListener listener); - void setOsdName(IBinder b, String name); void sendActiveSource(IBinder b); void sendInactiveSource(IBinder b); void sendImageViewOn(IBinder b); void sendTextViewOn(IBinder b); - void sendGiveDevicePowerStatus(IBinder b, int address); + boolean isTvOn(IBinder b); void sendMessage(IBinder b, in HdmiCecMessage message); } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 81ad28b..a355d1e 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -647,6 +647,7 @@ public class InputMethodService extends AbstractInputMethodService { getApplicationInfo().targetSdkVersion, android.R.style.Theme_InputMethod, android.R.style.Theme_Holo_InputMethod, + android.R.style.Theme_DeviceDefault_InputMethod, android.R.style.Theme_DeviceDefault_InputMethod); super.setTheme(mTheme); super.onCreate(); diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index d8e8e2c..377ed88 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -211,6 +211,7 @@ public final class NsdManager { private Context mContext; private static final int INVALID_LISTENER_KEY = 0; + private static final int BUSY_LISTENER_KEY = -1; private int mListenerKey = 1; private final SparseArray mListenerMap = new SparseArray(); private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<NsdServiceInfo>(); @@ -317,71 +318,74 @@ public final class NsdManager { Log.d(TAG, "Stale key " + message.arg2); return; } - boolean listenerRemove = true; NsdServiceInfo ns = getNsdService(message.arg2); switch (message.what) { case DISCOVER_SERVICES_STARTED: String s = getNsdServiceInfoType((NsdServiceInfo) message.obj); ((DiscoveryListener) listener).onDiscoveryStarted(s); - // Keep listener until stop discovery - listenerRemove = false; break; case DISCOVER_SERVICES_FAILED: + removeListener(message.arg2); ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns), message.arg1); break; case SERVICE_FOUND: ((DiscoveryListener) listener).onServiceFound((NsdServiceInfo) message.obj); - // Keep listener until stop discovery - listenerRemove = false; break; case SERVICE_LOST: ((DiscoveryListener) listener).onServiceLost((NsdServiceInfo) message.obj); - // Keep listener until stop discovery - listenerRemove = false; break; case STOP_DISCOVERY_FAILED: + removeListener(message.arg2); ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns), message.arg1); break; case STOP_DISCOVERY_SUCCEEDED: + removeListener(message.arg2); ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns)); break; case REGISTER_SERVICE_FAILED: + removeListener(message.arg2); ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1); break; case REGISTER_SERVICE_SUCCEEDED: ((RegistrationListener) listener).onServiceRegistered( (NsdServiceInfo) message.obj); - // Keep listener until unregister - listenerRemove = false; break; case UNREGISTER_SERVICE_FAILED: + removeListener(message.arg2); ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1); break; case UNREGISTER_SERVICE_SUCCEEDED: + removeListener(message.arg2); ((RegistrationListener) listener).onServiceUnregistered(ns); break; case RESOLVE_SERVICE_FAILED: + removeListener(message.arg2); ((ResolveListener) listener).onResolveFailed(ns, message.arg1); break; case RESOLVE_SERVICE_SUCCEEDED: + removeListener(message.arg2); ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj); break; default: Log.d(TAG, "Ignored " + message); break; } - if (listenerRemove) { - removeListener(message.arg2); - } } } + // if the listener is already in the map, reject it. Otherwise, add it and + // return its key. + private int putListener(Object listener, NsdServiceInfo s) { if (listener == null) return INVALID_LISTENER_KEY; int key; synchronized (mMapLock) { + int valueIndex = mListenerMap.indexOfValue(listener); + if (valueIndex != -1) { + return BUSY_LISTENER_KEY; + } do { key = mListenerKey++; } while (key == INVALID_LISTENER_KEY); @@ -422,7 +426,6 @@ public final class NsdManager { return INVALID_LISTENER_KEY; } - private String getNsdServiceInfoType(NsdServiceInfo s) { if (s == null) return "?"; return s.getServiceType(); @@ -449,14 +452,18 @@ public final class NsdManager { * Register a service to be discovered by other services. * * <p> The function call immediately returns after sending a request to register service - * to the framework. The application is notified of a success to initiate - * discovery through the callback {@link RegistrationListener#onServiceRegistered} or a failure + * to the framework. The application is notified of a successful registration + * through the callback {@link RegistrationListener#onServiceRegistered} or a failure * through {@link RegistrationListener#onRegistrationFailed}. * + * <p> The application should call {@link #unregisterService} when the service + * registration is no longer required, and/or whenever the application is stopped. + * * @param serviceInfo The service being registered * @param protocolType The service discovery protocol * @param listener The listener notifies of a successful registration and is used to * unregister this service through a call on {@link #unregisterService}. Cannot be null. + * Cannot be in use for an active service registration. */ public void registerService(NsdServiceInfo serviceInfo, int protocolType, RegistrationListener listener) { @@ -473,8 +480,11 @@ public final class NsdManager { if (protocolType != PROTOCOL_DNS_SD) { throw new IllegalArgumentException("Unsupported protocol"); } - mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, putListener(listener, serviceInfo), - serviceInfo); + int key = putListener(listener, serviceInfo); + if (key == BUSY_LISTENER_KEY) { + throw new IllegalArgumentException("listener already in use"); + } + mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo); } /** @@ -484,7 +494,11 @@ public final class NsdManager { * * @param listener This should be the listener object that was passed to * {@link #registerService}. It identifies the service that should be unregistered - * and notifies of a successful unregistration. + * and notifies of a successful or unsuccessful unregistration via the listener + * callbacks. In API versions 20 and above, the listener object may be used for + * another service registration once the callback has been called. In API versions <= 19, + * there is no entirely reliable way to know when a listener may be re-used, and a new + * listener should be created for each service registration request. */ public void unregisterService(RegistrationListener listener) { int id = getListenerKey(listener); @@ -514,12 +528,16 @@ public final class NsdManager { * <p> Upon failure to start, service discovery is not active and application does * not need to invoke {@link #stopServiceDiscovery} * + * <p> The application should call {@link #stopServiceDiscovery} when discovery of this + * service type is no longer required, and/or whenever the application is paused or + * stopped. + * * @param serviceType The service type being discovered. Examples include "_http._tcp" for * http services or "_ipp._tcp" for printers * @param protocolType The service discovery protocol * @param listener The listener notifies of a successful discovery and is used * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. - * Cannot be null. + * Cannot be null. Cannot be in use for an active service discovery. */ public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { if (listener == null) { @@ -535,11 +553,17 @@ public final class NsdManager { NsdServiceInfo s = new NsdServiceInfo(); s.setServiceType(serviceType); - mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, putListener(listener, s), s); + + int key = putListener(listener, s); + if (key == BUSY_LISTENER_KEY) { + throw new IllegalArgumentException("listener already in use"); + } + + mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s); } /** - * Stop service discovery initiated with {@link #discoverServices}. An active service + * Stop service discovery initiated with {@link #discoverServices}. An active service * discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted} * and it stays active until the application invokes a stop service discovery. A successful * stop is notified to with a call to {@link DiscoveryListener#onDiscoveryStopped}. @@ -548,7 +572,11 @@ public final class NsdManager { * {@link DiscoveryListener#onStopDiscoveryFailed}. * * @param listener This should be the listener object that was passed to {@link #discoverServices}. - * It identifies the discovery that should be stopped and notifies of a successful stop. + * It identifies the discovery that should be stopped and notifies of a successful or + * unsuccessful stop. In API versions 20 and above, the listener object may be used for + * another service discovery once the callback has been called. In API versions <= 19, + * there is no entirely reliable way to know when a listener may be re-used, and a new + * listener should be created for each service discovery request. */ public void stopServiceDiscovery(DiscoveryListener listener) { int id = getListenerKey(listener); @@ -568,6 +596,7 @@ public final class NsdManager { * * @param serviceInfo service to be resolved * @param listener to receive callback upon success or failure. Cannot be null. + * Cannot be in use for an active service resolution. */ public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) { if (TextUtils.isEmpty(serviceInfo.getServiceName()) || @@ -577,8 +606,13 @@ public final class NsdManager { if (listener == null) { throw new IllegalArgumentException("listener cannot be null"); } - mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, putListener(listener, serviceInfo), - serviceInfo); + + int key = putListener(listener, serviceInfo); + + if (key == BUSY_LISTENER_KEY) { + throw new IllegalArgumentException("listener already in use"); + } + mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo); } /** Internal use only @hide */ diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 7647c22..de9eeff 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -153,11 +153,11 @@ public class DreamService extends Service implements Window.Callback { private final Handler mHandler = new Handler(); private IBinder mWindowToken; private Window mWindow; - private WindowManager mWindowManager; - private boolean mInteractive = false; + private boolean mInteractive; private boolean mLowProfile = true; - private boolean mFullscreen = false; + private boolean mFullscreen; private boolean mScreenBright = true; + private boolean mStarted; private boolean mFinished; private boolean mCanDoze; private boolean mDozing; @@ -340,7 +340,7 @@ public class DreamService extends Service implements Window.Callback { * @return The current window manager, or null if the dream is not started. */ public WindowManager getWindowManager() { - return mWindowManager; + return mWindow != null ? mWindow.getWindowManager() : null; } /** @@ -623,7 +623,7 @@ public class DreamService extends Service implements Window.Callback { * @hide experimental */ public DozeHardware getDozeHardware() { - if (mCanDoze && mDozeHardware == null) { + if (mCanDoze && mDozeHardware == null && mWindowToken != null) { try { IDozeHardware hardware = mSandman.getDozeHardware(mWindowToken); if (hardware != null) { @@ -701,24 +701,25 @@ public class DreamService extends Service implements Window.Callback { * Must run on mHandler. */ private final void detach() { - if (mWindow == null) { - // already detached! - return; + if (mStarted) { + if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()"); + mStarted = false; + onDreamingStopped(); } - if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()"); - onDreamingStopped(); - - if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager"); - - // force our window to be removed synchronously - mWindowManager.removeViewImmediate(mWindow.getDecorView()); - // the following will print a log message if it finds any other leaked windows - WindowManagerGlobal.getInstance().closeAll(mWindowToken, - this.getClass().getName(), "Dream"); + if (mWindow != null) { + // force our window to be removed synchronously + if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager"); + mWindow.getWindowManager().removeViewImmediate(mWindow.getDecorView()); + mWindow = null; + } - mWindow = null; - mWindowToken = null; + if (mWindowToken != null) { + // the following will print a log message if it finds any other leaked windows + WindowManagerGlobal.getInstance().closeAll(mWindowToken, + this.getClass().getName(), "Dream"); + mWindowToken = null; + } } /** @@ -746,12 +747,13 @@ public class DreamService extends Service implements Window.Callback { if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId()); mWindowToken = windowToken; + mCanDoze = canDoze; + mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.requestFeature(Window.FEATURE_NO_TITLE); mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000)); mWindow.setFormat(PixelFormat.OPAQUE); - mCanDoze = canDoze; if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s", windowToken, WindowManager.LayoutParams.TYPE_DREAM)); @@ -769,26 +771,28 @@ public class DreamService extends Service implements Window.Callback { | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0) ); mWindow.setAttributes(lp); - - if (mDebug) Slog.v(TAG, "Created and attached window: " + mWindow); - mWindow.setWindowManager(null, windowToken, "dream", true); - mWindowManager = mWindow.getWindowManager(); - if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId()); applySystemUiVisibilityFlags( (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0), View.SYSTEM_UI_FLAG_LOW_PROFILE); - getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); + + try { + getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); + } catch (WindowManager.BadTokenException ex) { + // This can happen because the dream manager service will remove the token + // immediately without necessarily waiting for the dream to start. + // We should receive a finish message soon. + Slog.i(TAG, "attach() called after window token already removed, dream will " + + "finish soon"); + mWindow = null; + return; + } // start it up - mHandler.post(new Runnable() { - @Override - public void run() { - if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()"); - onDreamingStarted(); - } - }); + if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()"); + mStarted = true; + onDreamingStarted(); } private void safelyFinish() { @@ -831,7 +835,7 @@ public class DreamService extends Service implements Window.Callback { WindowManager.LayoutParams lp = mWindow.getAttributes(); lp.flags = applyFlags(lp.flags, flags, mask); mWindow.setAttributes(lp); - mWindowManager.updateViewLayout(mWindow.getDecorView(), lp); + mWindow.getWindowManager().updateViewLayout(mWindow.getDecorView(), lp); } } diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index a27c313..26eaef8 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -16,6 +16,7 @@ package android.view; +import android.annotation.NonNull; import android.graphics.Matrix; import android.graphics.Outline; @@ -196,18 +197,20 @@ public class RenderNode { } /** - * Starts recording the display list. All operations performed on the - * returned canvas are recorded and stored in this display list. + * Starts recording a display list for the render node. All + * operations performed on the returned canvas are recorded and + * stored in this display list. * - * Calling this method will mark the display list invalid until - * {@link #end()} is called. Only valid display lists can be replayed. + * Calling this method will mark the render node invalid until + * {@link #end(HardwareRenderer, HardwareCanvas)} is called. + * Only valid render nodes can be replayed. * - * @param width The width of the display list's viewport - * @param height The height of the display list's viewport + * @param width The width of the recording viewport + * @param height The height of the recording viewport * * @return A canvas to record drawing operations. * - * @see #end() + * @see #end(HardwareRenderer, HardwareCanvas) * @see #isValid() */ public HardwareCanvas start(int width, int height) { @@ -284,7 +287,23 @@ public class RenderNode { } /////////////////////////////////////////////////////////////////////////// - // DisplayList Property Setters + // Matrix manipulation + /////////////////////////////////////////////////////////////////////////// + + public boolean hasIdentityMatrix() { + return nHasIdentityMatrix(mNativeDisplayList); + } + + public void getMatrix(@NonNull Matrix outMatrix) { + nGetTransformMatrix(mNativeDisplayList, outMatrix.native_instance); + } + + public void getInverseMatrix(@NonNull Matrix outMatrix) { + nGetInverseTransformMatrix(mNativeDisplayList, outMatrix.native_instance); + } + + /////////////////////////////////////////////////////////////////////////// + // RenderProperty Setters /////////////////////////////////////////////////////////////////////////// /** @@ -301,7 +320,7 @@ public class RenderNode { } /** - * Set whether the display list should clip itself to its bounds. This property is controlled by + * Set whether the Render node should clip itself to its bounds. This property is controlled by * the view's parent. * * @param clipToBounds true if the display list should clip to its bounds @@ -312,9 +331,7 @@ public class RenderNode { /** * Sets whether the display list should be drawn immediately after the - * closest ancestor display list where isolateZVolume is true. If the - * display list itself satisfies this constraint, changing this attribute - * has no effect on drawing order. + * closest ancestor display list containing a projection receiver. * * @param shouldProject true if the display list should be projected onto a * containing volume. @@ -373,9 +390,6 @@ public class RenderNode { * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.) * * @param matrix A transform matrix to apply to this display list - * - * @see #getMatrix(android.graphics.Matrix) - * @see #getMatrix() */ public void setStaticMatrix(Matrix matrix) { nSetStaticMatrix(mNativeDisplayList, matrix.native_instance); @@ -613,28 +627,6 @@ public class RenderNode { } /** - * Sets all of the transform-related values of the display list - * - * @param alpha The alpha value of the display list - * @param translationX The translationX value of the display list - * @param translationY The translationY value of the display list - * @param rotation The rotation value of the display list - * @param rotationX The rotationX value of the display list - * @param rotationY The rotationY value of the display list - * @param scaleX The scaleX value of the display list - * @param scaleY The scaleY value of the display list - * - * @hide - */ - public void setTransformationInfo(float alpha, - float translationX, float translationY, float translationZ, - float rotation, float rotationX, float rotationY, float scaleX, float scaleY) { - nSetTransformationInfo(mNativeDisplayList, alpha, - translationX, translationY, translationZ, - rotation, rotationX, rotationY, scaleX, scaleY); - } - - /** * Sets the pivot value for the display list on the X axis * * @param pivotX The pivot value of the display list on the X axis, in pixels @@ -676,6 +668,10 @@ public class RenderNode { return nGetPivotY(mNativeDisplayList); } + public boolean isPivotExplicitlySet() { + return nIsPivotExplicitlySet(mNativeDisplayList); + } + /** * Sets the camera distance for the display list. Refer to * {@link View#setCameraDistance(float)} for more information on how to @@ -842,6 +838,12 @@ public class RenderNode { private static native void nDestroyDisplayList(long displayList); private static native void nSetDisplayListName(long displayList, String name); + // Matrix + + private static native void nGetTransformMatrix(long displayList, long nativeMatrix); + private static native void nGetInverseTransformMatrix(long displayList, long nativeMatrix); + private static native boolean nHasIdentityMatrix(long displayList); + // Properties private static native void nOffsetTopAndBottom(long displayList, float offset); @@ -877,9 +879,6 @@ public class RenderNode { private static native void nSetRotationY(long displayList, float rotationY); private static native void nSetScaleX(long displayList, float scaleX); private static native void nSetScaleY(long displayList, float scaleY); - private static native void nSetTransformationInfo(long displayList, float alpha, - float translationX, float translationY, float translationZ, - float rotation, float rotationX, float rotationY, float scaleX, float scaleY); private static native void nSetStaticMatrix(long displayList, long nativeMatrix); private static native void nSetAnimationMatrix(long displayList, long animationMatrix); @@ -898,6 +897,7 @@ public class RenderNode { private static native float nGetRotation(long displayList); private static native float nGetRotationX(long displayList); private static native float nGetRotationY(long displayList); + private static native boolean nIsPivotExplicitlySet(long displayList); private static native float nGetPivotX(long displayList); private static native float nGetPivotY(long displayList); private static native void nOutput(long displayList); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 5be4698..6c414f6 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1792,12 +1792,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static final int PFLAG_HOVERED = 0x10000000; /** - * Indicates that pivotX or pivotY were explicitly set and we should not assume the center - * for transform operations - * - * @hide + * no longer needed, should be reused */ - private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000; + private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000; /** {@hide} */ static final int PFLAG_ACTIVATED = 0x40000000; @@ -2930,123 +2927,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, static class TransformationInfo { /** * The transform matrix for the View. This transform is calculated internally - * based on the rotation, scaleX, and scaleY properties. The identity matrix - * is used by default. Do *not* use this variable directly; instead call - * getMatrix(), which will automatically recalculate the matrix if necessary - * to get the correct matrix based on the latest rotation and scale properties. + * based on the translation, rotation, and scale properties. + * + * Do *not* use this variable directly; instead call getMatrix(), which will + * load the value from the View's RenderNode. */ private final Matrix mMatrix = new Matrix(); /** - * The transform matrix for the View. This transform is calculated internally - * based on the rotation, scaleX, and scaleY properties. The identity matrix - * is used by default. Do *not* use this variable directly; instead call - * getInverseMatrix(), which will automatically recalculate the matrix if necessary - * to get the correct matrix based on the latest rotation and scale properties. + * The inverse transform matrix for the View. This transform is calculated + * internally based on the translation, rotation, and scale properties. + * + * Do *not* use this variable directly; instead call getInverseMatrix(), + * which will load the value from the View's RenderNode. */ private Matrix mInverseMatrix; /** - * An internal variable that tracks whether we need to recalculate the - * transform matrix, based on whether the rotation or scaleX/Y properties - * have changed since the matrix was last calculated. - */ - boolean mMatrixDirty = false; - - /** - * An internal variable that tracks whether we need to recalculate the - * transform matrix, based on whether the rotation or scaleX/Y properties - * have changed since the matrix was last calculated. - */ - private boolean mInverseMatrixDirty = true; - - /** - * A variable that tracks whether we need to recalculate the - * transform matrix, based on whether the rotation or scaleX/Y properties - * have changed since the matrix was last calculated. This variable - * is only valid after a call to updateMatrix() or to a function that - * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix(). - */ - private boolean mMatrixIsIdentity = true; - - /** - * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set. - */ - private Camera mCamera = null; - - /** - * This matrix is used when computing the matrix for 3D rotations. - */ - private Matrix matrix3D = null; - - /** - * These prev values are used to recalculate a centered pivot point when necessary. The - * pivot point is only used in matrix operations (when rotation, scale, or translation are - * set), so thes values are only used then as well. - */ - private int mPrevWidth = -1; - private int mPrevHeight = -1; - - /** - * The degrees rotation around the vertical axis through the pivot point. - */ - @ViewDebug.ExportedProperty - float mRotationY = 0f; - - /** - * The degrees rotation around the horizontal axis through the pivot point. - */ - @ViewDebug.ExportedProperty - float mRotationX = 0f; - - /** - * The degrees rotation around the pivot point. - */ - @ViewDebug.ExportedProperty - float mRotation = 0f; - - /** - * The amount of translation of the object away from its left property (post-layout). - */ - @ViewDebug.ExportedProperty - float mTranslationX = 0f; - - /** - * The amount of translation of the object away from its top property (post-layout). - */ - @ViewDebug.ExportedProperty - float mTranslationY = 0f; - - @ViewDebug.ExportedProperty - float mTranslationZ = 0f; - - /** - * The amount of scale in the x direction around the pivot point. A - * value of 1 means no scaling is applied. - */ - @ViewDebug.ExportedProperty - float mScaleX = 1f; - - /** - * The amount of scale in the y direction around the pivot point. A - * value of 1 means no scaling is applied. - */ - @ViewDebug.ExportedProperty - float mScaleY = 1f; - - /** - * The x location of the point around which the view is rotated and scaled. - */ - @ViewDebug.ExportedProperty - float mPivotX = 0f; - - /** - * The y location of the point around which the view is rotated and scaled. - */ - @ViewDebug.ExportedProperty - float mPivotY = 0f; - - /** * The opacity of the View. This is a value from 0 to 1, where 0 means * completely transparent and 1 means completely opaque. */ @@ -3557,7 +3454,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * of the View content. Its DisplayList content is cleared on temporary detach and reset on * cleanup. */ - RenderNode mRenderNode; + final RenderNode mRenderNode; /** * Set to true when the view is sending hover accessibility events because it @@ -3608,6 +3505,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); mUserPaddingStart = UNDEFINED_PADDING; mUserPaddingEnd = UNDEFINED_PADDING; + mRenderNode = RenderNode.create(getClass().getName()); if (!sCompatibilityDone && context != null) { final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; @@ -4172,6 +4070,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ View() { mResources = null; + mRenderNode = RenderNode.create(getClass().getName()); } public String toString() { @@ -4847,10 +4746,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final float x = r.exactCenterX(); final float y = r.exactCenterY(); - mBackground.setHotspot(Drawable.HOTSPOT_FOCUS, x, y); + mBackground.setHotspot(R.attr.state_focused, x, y); if (!focused) { - mBackground.removeHotspot(Drawable.HOTSPOT_FOCUS); + mBackground.removeHotspot(R.attr.state_focused); } } } @@ -9092,6 +8991,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } removeTapCallback(); + } else { + clearHotspot(R.attr.state_pressed); } break; @@ -9204,6 +9105,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private void removeUnsetPressCallback() { if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) { + clearHotspot(R.attr.state_pressed); setPressed(false); removeCallbacks(mUnsetPressedState); } @@ -9682,21 +9584,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return The current transform matrix for the view */ public Matrix getMatrix() { - if (mTransformationInfo != null) { - updateMatrix(); - return mTransformationInfo.mMatrix; - } - return Matrix.IDENTITY_MATRIX; - } - - /** - * Utility function to determine if the value is far enough away from zero to be - * considered non-zero. - * @param value A floating point value to check for zero-ness - * @return whether the passed-in value is far enough away from zero to be considered non-zero - */ - private static boolean nonzero(float value) { - return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON); + ensureTransformationInfo(); + final Matrix matrix = mTransformationInfo.mMatrix; + mRenderNode.getMatrix(matrix); + return matrix; } /** @@ -9706,11 +9597,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return True if the transform matrix is the identity matrix, false otherwise. */ final boolean hasIdentityMatrix() { - if (mTransformationInfo != null) { - updateMatrix(); - return mTransformationInfo.mMatrixIsIdentity; - } - return true; + return mRenderNode.hasIdentityMatrix(); } void ensureTransformationInfo() { @@ -9719,59 +9606,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } - void ensureRenderNode() { - if (mRenderNode == null) { - mRenderNode = RenderNode.create(getClass().getName()); - } - } - - /** - * Recomputes the transform matrix if necessary. - */ - private void updateMatrix() { - final TransformationInfo info = mTransformationInfo; - if (info == null) { - return; - } - if (info.mMatrixDirty) { - // transform-related properties have changed since the last time someone - // asked for the matrix; recalculate it with the current values - - // Figure out if we need to update the pivot point - if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { - if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) { - info.mPrevWidth = mRight - mLeft; - info.mPrevHeight = mBottom - mTop; - info.mPivotX = info.mPrevWidth / 2f; - info.mPivotY = info.mPrevHeight / 2f; - } - } - info.mMatrix.reset(); - if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) { - info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY); - info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY); - info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY); - } else { - if (info.mCamera == null) { - info.mCamera = new Camera(); - info.matrix3D = new Matrix(); - } - info.mCamera.save(); - info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY); - info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation); - info.mCamera.getMatrix(info.matrix3D); - info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY); - info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX, - info.mPivotY + info.mTranslationY); - info.mMatrix.postConcat(info.matrix3D); - info.mCamera.restore(); - } - info.mMatrixDirty = false; - info.mMatrixIsIdentity = info.mMatrix.isIdentity(); - info.mInverseMatrixDirty = true; - } - } - /** * Utility method to retrieve the inverse of the current mMatrix property. * We cache the matrix to avoid recalculating it when transform properties @@ -9780,19 +9614,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return The inverse of the current matrix of this view. */ final Matrix getInverseMatrix() { - final TransformationInfo info = mTransformationInfo; - if (info != null) { - updateMatrix(); - if (info.mInverseMatrixDirty) { - if (info.mInverseMatrix == null) { - info.mInverseMatrix = new Matrix(); - } - info.mMatrix.invert(info.mInverseMatrix); - info.mInverseMatrixDirty = false; - } - return info.mInverseMatrix; + ensureTransformationInfo(); + if (mTransformationInfo.mInverseMatrix == null) { + mTransformationInfo.mInverseMatrix = new Matrix(); } - return Matrix.IDENTITY_MATRIX; + final Matrix matrix = mTransformationInfo.mInverseMatrix; + mRenderNode.getInverseMatrix(matrix); + return matrix; } /** @@ -9803,14 +9631,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return The distance along the Z axis. */ public float getCameraDistance() { - ensureTransformationInfo(); final float dpi = mResources.getDisplayMetrics().densityDpi; - final TransformationInfo info = mTransformationInfo; - if (info.mCamera == null) { - info.mCamera = new Camera(); - info.matrix3D = new Matrix(); - } - return -(info.mCamera.getLocationZ() * dpi); + return -(mRenderNode.getCameraDistance() * dpi); } /** @@ -9853,27 +9675,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @see #setRotationY(float) */ public void setCameraDistance(float distance) { - invalidateViewProperty(true, false); - - ensureTransformationInfo(); final float dpi = mResources.getDisplayMetrics().densityDpi; - final TransformationInfo info = mTransformationInfo; - if (info.mCamera == null) { - info.mCamera = new Camera(); - info.matrix3D = new Matrix(); - } - - info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi); - info.mMatrixDirty = true; + invalidateViewProperty(true, false); + mRenderNode.setCameraDistance(-Math.abs(distance) / dpi); invalidateViewProperty(false, false); - if (mRenderNode != null) { - mRenderNode.setCameraDistance(-Math.abs(distance) / dpi); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } /** @@ -9887,7 +9695,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getRotation() { - return mTransformationInfo != null ? mTransformationInfo.mRotation : 0; + return mRenderNode.getRotation(); } /** @@ -9905,21 +9713,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_rotation */ public void setRotation(float rotation) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - if (info.mRotation != rotation) { + if (rotation != getRotation()) { // Double-invalidation is necessary to capture view's old and new areas invalidateViewProperty(true, false); - info.mRotation = rotation; - info.mMatrixDirty = true; + mRenderNode.setRotation(rotation); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setRotation(rotation); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -9934,7 +9734,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getRotationY() { - return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0; + return mRenderNode.getRotationY(); } /** @@ -9957,20 +9757,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_rotationY */ public void setRotationY(float rotationY) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - if (info.mRotationY != rotationY) { + if (rotationY != getRotationY()) { invalidateViewProperty(true, false); - info.mRotationY = rotationY; - info.mMatrixDirty = true; + mRenderNode.setRotationY(rotationY); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setRotationY(rotationY); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -9985,7 +9777,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getRotationX() { - return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0; + return mRenderNode.getRotationX(); } /** @@ -10008,20 +9800,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_rotationX */ public void setRotationX(float rotationX) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - if (info.mRotationX != rotationX) { + if (rotationX != getRotationX()) { invalidateViewProperty(true, false); - info.mRotationX = rotationX; - info.mMatrixDirty = true; + mRenderNode.setRotationX(rotationX); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setRotationX(rotationX); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -10037,7 +9821,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getScaleX() { - return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1; + return mRenderNode.getScaleX(); } /** @@ -10051,20 +9835,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_scaleX */ public void setScaleX(float scaleX) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - if (info.mScaleX != scaleX) { + if (scaleX != getScaleX()) { invalidateViewProperty(true, false); - info.mScaleX = scaleX; - info.mMatrixDirty = true; + mRenderNode.setScaleX(scaleX); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setScaleX(scaleX); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -10080,7 +9856,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getScaleY() { - return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1; + return mRenderNode.getScaleY(); } /** @@ -10094,20 +9870,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_scaleY */ public void setScaleY(float scaleY) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - if (info.mScaleY != scaleY) { + if (scaleY != getScaleY()) { invalidateViewProperty(true, false); - info.mScaleY = scaleY; - info.mMatrixDirty = true; + mRenderNode.setScaleY(scaleY); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setScaleY(scaleY); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -10125,7 +9893,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getPivotX() { - return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0; + return mRenderNode.getPivotX(); } /** @@ -10144,23 +9912,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_transformPivotX */ public void setPivotX(float pivotX) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == - PFLAG_PIVOT_EXPLICITLY_SET; - if (info.mPivotX != pivotX || !pivotSet) { - mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET; + if (mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) { invalidateViewProperty(true, false); - info.mPivotX = pivotX; - info.mMatrixDirty = true; + mRenderNode.setPivotX(pivotX); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setPivotX(pivotX); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -10178,7 +9935,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getPivotY() { - return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0; + return mRenderNode.getPivotY(); } /** @@ -10196,23 +9953,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_transformPivotY */ public void setPivotY(float pivotY) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == - PFLAG_PIVOT_EXPLICITLY_SET; - if (info.mPivotY != pivotY || !pivotSet) { - mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET; + if (mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) { invalidateViewProperty(true, false); - info.mPivotY = pivotY; - info.mMatrixDirty = true; + mRenderNode.setPivotY(pivotY); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setPivotY(pivotY); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -10290,9 +10036,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { mPrivateFlags &= ~PFLAG_ALPHA_SET; invalidateViewProperty(true, false); - if (mRenderNode != null) { - mRenderNode.setAlpha(getFinalAlpha()); - } + mRenderNode.setAlpha(getFinalAlpha()); } } } @@ -10317,9 +10061,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return true; } else { mPrivateFlags &= ~PFLAG_ALPHA_SET; - if (mRenderNode != null) { - mRenderNode.setAlpha(getFinalAlpha()); - } + mRenderNode.setAlpha(getFinalAlpha()); } } return false; @@ -10340,9 +10082,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mTransformationInfo.mTransitionAlpha = alpha; mPrivateFlags &= ~PFLAG_ALPHA_SET; invalidateViewProperty(true, false); - if (mRenderNode != null) { - mRenderNode.setAlpha(getFinalAlpha()); - } + mRenderNode.setAlpha(getFinalAlpha()); } } @@ -10389,9 +10129,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public final void setTop(int top) { if (top != mTop) { - updateMatrix(); - final boolean matrixIsIdentity = mTransformationInfo == null - || mTransformationInfo.mMatrixIsIdentity; + final boolean matrixIsIdentity = hasIdentityMatrix(); if (matrixIsIdentity) { if (mAttachInfo != null) { int minTop; @@ -10414,17 +10152,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int oldHeight = mBottom - mTop; mTop = top; - if (mRenderNode != null) { - mRenderNode.setTop(mTop); - } + mRenderNode.setTop(mTop); sizeChange(width, mBottom - mTop, width, oldHeight); if (!matrixIsIdentity) { - if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { - // A change in dimension means an auto-centered pivot point changes, too - mTransformationInfo.mMatrixDirty = true; - } mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation invalidate(true); } @@ -10465,9 +10197,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public final void setBottom(int bottom) { if (bottom != mBottom) { - updateMatrix(); - final boolean matrixIsIdentity = mTransformationInfo == null - || mTransformationInfo.mMatrixIsIdentity; + final boolean matrixIsIdentity = hasIdentityMatrix(); if (matrixIsIdentity) { if (mAttachInfo != null) { int maxBottom; @@ -10487,17 +10217,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int oldHeight = mBottom - mTop; mBottom = bottom; - if (mRenderNode != null) { - mRenderNode.setBottom(mBottom); - } + mRenderNode.setBottom(mBottom); sizeChange(width, mBottom - mTop, width, oldHeight); if (!matrixIsIdentity) { - if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { - // A change in dimension means an auto-centered pivot point changes, too - mTransformationInfo.mMatrixDirty = true; - } mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation invalidate(true); } @@ -10529,9 +10253,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public final void setLeft(int left) { if (left != mLeft) { - updateMatrix(); - final boolean matrixIsIdentity = mTransformationInfo == null - || mTransformationInfo.mMatrixIsIdentity; + final boolean matrixIsIdentity = hasIdentityMatrix(); if (matrixIsIdentity) { if (mAttachInfo != null) { int minLeft; @@ -10554,17 +10276,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int height = mBottom - mTop; mLeft = left; - if (mRenderNode != null) { - mRenderNode.setLeft(left); - } + mRenderNode.setLeft(left); sizeChange(mRight - mLeft, height, oldWidth, height); if (!matrixIsIdentity) { - if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { - // A change in dimension means an auto-centered pivot point changes, too - mTransformationInfo.mMatrixDirty = true; - } mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation invalidate(true); } @@ -10596,9 +10312,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public final void setRight(int right) { if (right != mRight) { - updateMatrix(); - final boolean matrixIsIdentity = mTransformationInfo == null - || mTransformationInfo.mMatrixIsIdentity; + final boolean matrixIsIdentity = hasIdentityMatrix(); if (matrixIsIdentity) { if (mAttachInfo != null) { int maxRight; @@ -10618,17 +10332,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int height = mBottom - mTop; mRight = right; - if (mRenderNode != null) { - mRenderNode.setRight(mRight); - } + mRenderNode.setRight(mRight); sizeChange(mRight - mLeft, height, oldWidth, height); if (!matrixIsIdentity) { - if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { - // A change in dimension means an auto-centered pivot point changes, too - mTransformationInfo.mMatrixDirty = true; - } mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation invalidate(true); } @@ -10650,7 +10358,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getX() { - return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0); + return mLeft + getTranslationX(); } /** @@ -10673,7 +10381,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getY() { - return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0); + return mTop + getTranslationY(); } /** @@ -10697,7 +10405,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getTranslationX() { - return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0; + return mRenderNode.getTranslationX(); } /** @@ -10711,21 +10419,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_translationX */ public void setTranslationX(float translationX) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - if (info.mTranslationX != translationX) { - // Double-invalidation is necessary to capture view's old and new areas + if (translationX != getTranslationX()) { invalidateViewProperty(true, false); - info.mTranslationX = translationX; - info.mMatrixDirty = true; + mRenderNode.setTranslationX(translationX); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setTranslationX(translationX); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -10739,7 +10438,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getTranslationY() { - return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0; + return mRenderNode.getTranslationY(); } /** @@ -10753,20 +10452,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_translationY */ public void setTranslationY(float translationY) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - if (info.mTranslationY != translationY) { + if (translationY != getTranslationY()) { invalidateViewProperty(true, false); - info.mTranslationY = translationY; - info.mMatrixDirty = true; + mRenderNode.setTranslationY(translationY); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setTranslationY(translationY); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -10777,7 +10468,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty(category = "drawing") public float getTranslationZ() { - return mTransformationInfo != null ? mTransformationInfo.mTranslationZ : 0; + return mRenderNode.getTranslationZ(); } /** @@ -10786,20 +10477,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_translationZ */ public void setTranslationZ(float translationZ) { - ensureTransformationInfo(); - final TransformationInfo info = mTransformationInfo; - if (info.mTranslationZ != translationZ) { + if (translationZ != getTranslationZ()) { invalidateViewProperty(true, false); - info.mTranslationZ = translationZ; - info.mMatrixDirty = true; + mRenderNode.setTranslationZ(translationZ); invalidateViewProperty(false, true); - if (mRenderNode != null) { - mRenderNode.setTranslationZ(translationZ); - } - if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { - // View was rejected last time it was drawn by its parent; this may have changed - invalidateParentIfNeeded(); - } + + invalidateParentIfNeededAndWasQuickRejected(); } } @@ -10869,10 +10552,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } mOutline.set(outline); } - - if (mRenderNode != null) { - mRenderNode.setOutline(mOutline); - } + mRenderNode.setOutline(mOutline); } /** @@ -10907,9 +10587,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { mPrivateFlags3 &= ~PFLAG3_CLIP_TO_OUTLINE; } - if (mRenderNode != null) { - mRenderNode.setClipToOutline(clipToOutline); - } + mRenderNode.setClipToOutline(clipToOutline); } } @@ -10920,11 +10598,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public void setRevealClip(boolean shouldClip, boolean inverseClip, float x, float y, float radius) { - if (mRenderNode != null) { - mRenderNode.setRevealClip(shouldClip, inverseClip, x, y, radius); - // TODO: Handle this invalidate in a better way, or purely in native. - invalidate(); - } + mRenderNode.setRevealClip(shouldClip, inverseClip, x, y, radius); + // TODO: Handle this invalidate in a better way, or purely in native. + invalidate(); } /** @@ -10933,14 +10609,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param outRect The hit rectangle of the view. */ public void getHitRect(Rect outRect) { - updateMatrix(); - final TransformationInfo info = mTransformationInfo; - if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) { + if (hasIdentityMatrix() || mAttachInfo == null) { outRect.set(mLeft, mTop, mRight, mBottom); } else { final RectF tmpRect = mAttachInfo.mTmpTransformRect; tmpRect.set(0, 0, getWidth(), getHeight()); - info.mMatrix.mapRect(tmpRect); + getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect) outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop, (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop); } @@ -11029,11 +10703,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public void offsetTopAndBottom(int offset) { if (offset != 0) { - updateMatrix(); - final boolean matrixIsIdentity = mTransformationInfo == null - || mTransformationInfo.mMatrixIsIdentity; + final boolean matrixIsIdentity = hasIdentityMatrix(); if (matrixIsIdentity) { - if (mRenderNode != null) { + if (isHardwareAccelerated()) { invalidateViewProperty(false, false); } else { final ViewParent p = mParent; @@ -11061,8 +10733,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mTop += offset; mBottom += offset; - if (mRenderNode != null) { - mRenderNode.offsetTopAndBottom(offset); + mRenderNode.offsetTopAndBottom(offset); + if (isHardwareAccelerated()) { invalidateViewProperty(false, false); } else { if (!matrixIsIdentity) { @@ -11080,11 +10752,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public void offsetLeftAndRight(int offset) { if (offset != 0) { - updateMatrix(); - final boolean matrixIsIdentity = mTransformationInfo == null - || mTransformationInfo.mMatrixIsIdentity; + final boolean matrixIsIdentity = hasIdentityMatrix(); if (matrixIsIdentity) { - if (mRenderNode != null) { + if (isHardwareAccelerated()) { invalidateViewProperty(false, false); } else { final ViewParent p = mParent; @@ -11109,8 +10779,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mLeft += offset; mRight += offset; - if (mRenderNode != null) { - mRenderNode.offsetLeftAndRight(offset); + mRenderNode.offsetLeftAndRight(offset); + if (isHardwareAccelerated()) { invalidateViewProperty(false, false); } else { if (!matrixIsIdentity) { @@ -11490,7 +11160,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } // Damage the entire IsolatedZVolume recieving this view's shadow. - if (getTranslationZ() != 0) { + if (isHardwareAccelerated() && getTranslationZ() != 0) { damageShadowReceiver(); } } @@ -11553,7 +11223,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * list properties are not being used in this view */ void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { - if (mRenderNode == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) { + if (!isHardwareAccelerated() + || !mRenderNode.isValid() + || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) { if (invalidateParent) { invalidateParentCaches(); } @@ -11564,7 +11236,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { damageInParent(); } - if (invalidateParent && getTranslationZ() != 0) { + if (isHardwareAccelerated() && invalidateParent && getTranslationZ() != 0) { damageShadowReceiver(); } } @@ -11581,7 +11253,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final Rect r = ai.mTmpInvalRect; r.set(0, 0, mRight - mLeft, mBottom - mTop); if (mParent instanceof ViewGroup) { - ((ViewGroup) mParent).invalidateChildFast(this, r); + ((ViewGroup) mParent).damageChild(this, r); } else { mParent.invalidateChild(this, r); } @@ -11634,6 +11306,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * @hide + */ + protected void invalidateParentIfNeededAndWasQuickRejected() { + if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } + } + + /** * Indicates whether this View is opaque. An opaque View guarantees that it will * draw all the pixels overlapping its bounds using a fully opaque color. * @@ -13976,13 +13658,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @hide */ public RenderNode getDisplayList() { - ensureRenderNode(); updateDisplayListIfDirty(mRenderNode, false); return mRenderNode; } private void resetDisplayList() { - if (mRenderNode != null && mRenderNode.isValid()) { + if (mRenderNode.isValid()) { mRenderNode.destroyDisplayListData(); } @@ -14577,21 +14258,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * This method is called by getDisplayList() when a display list is created or re-rendered. - * It sets or resets the current value of all properties on that display list (resetting is - * necessary when a display list is being re-created, because we need to make sure that - * previously-set transform values + * This method is called by getDisplayList() when a display list is recorded for a View. + * It pushes any properties to the RenderNode that aren't managed by the RenderNode. */ - void setDisplayListProperties(RenderNode displayList) { - if (displayList != null) { - displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); - displayList.setHasOverlappingRendering(hasOverlappingRendering()); + void setDisplayListProperties(RenderNode renderNode) { + if (renderNode != null) { + renderNode.setHasOverlappingRendering(hasOverlappingRendering()); if (mParent instanceof ViewGroup) { - displayList.setClipToBounds( + renderNode.setClipToBounds( (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0); } - displayList.setOutline(mOutline); - displayList.setClipToOutline(getClipToOutline()); float alpha = 1; if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { @@ -14604,7 +14280,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, alpha = t.getAlpha(); } if ((transformType & Transformation.TYPE_MATRIX) != 0) { - displayList.setStaticMatrix(t.getMatrix()); + renderNode.setStaticMatrix(t.getMatrix()); } } } @@ -14617,23 +14293,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, alpha = 1; } } - displayList.setTransformationInfo(alpha, - mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY, - mTransformationInfo.mTranslationZ, - mTransformationInfo.mRotation, mTransformationInfo.mRotationX, - mTransformationInfo.mRotationY, mTransformationInfo.mScaleX, - mTransformationInfo.mScaleY); - if (mTransformationInfo.mCamera == null) { - mTransformationInfo.mCamera = new Camera(); - mTransformationInfo.matrix3D = new Matrix(); - } - displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ()); - if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) { - displayList.setPivotX(getPivotX()); - displayList.setPivotY(getPivotY()); - } + renderNode.setAlpha(alpha); } else if (alpha < 1) { - displayList.setAlpha(alpha); + renderNode.setAlpha(alpha); } } } @@ -14680,8 +14342,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } transformToApply = parent.getChildTransformation(); } else { - if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) == - PFLAG3_VIEW_IS_ANIMATING_TRANSFORM && mRenderNode != null) { + if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) { // No longer animating: clear out old animation matrix mRenderNode.setAnimationMatrix(null); mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; @@ -15196,9 +14857,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if ((mPrivateFlags3 & PFLAG3_OUTLINE_DEFINED) == 0) { // Outline not currently define, query from background mOutline = background.getOutline(); - if (mRenderNode != null) { - mRenderNode.setOutline(mOutline); - } + mRenderNode.setOutline(mOutline); } } @@ -15533,20 +15192,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mTop = top; mRight = right; mBottom = bottom; - if (mRenderNode != null) { - mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); - } + mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); mPrivateFlags |= PFLAG_HAS_BOUNDS; if (sizeChanged) { - if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { - // A change in dimension means an auto-centered pivot point changes, too - if (mTransformationInfo != null) { - mTransformationInfo.mMatrixDirty = true; - } - } sizeChange(newWidth, newHeight, oldWidth, oldHeight); } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index bcc82fb..d2c6302 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -4449,7 +4449,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * * @hide */ - public void invalidateChildFast(View child, final Rect dirty) { + public void damageChild(View child, final Rect dirty) { ViewParent parent = this; final AttachInfo attachInfo = mAttachInfo; @@ -4472,7 +4472,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager parentVG.invalidate(); parent = null; } else { - parent = parentVG.invalidateChildInParentFast(left, top, dirty); + parent = parentVG.damageChildInParent(left, top, dirty); left = parentVG.mLeft; top = parentVG.mTop; } @@ -4494,9 +4494,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * * @hide */ - protected ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) { - if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN || - (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) { + protected ViewParent damageChildInParent(int left, int top, final Rect dirty) { + if ((mPrivateFlags & PFLAG_DRAWN) != 0 + || (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) != 0) { dirty.offset(left - mScrollX, top - mScrollY); if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0) { dirty.union(0, 0, mRight - mLeft, mBottom - mTop); diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java index 47de780..0cf9ddd 100644 --- a/core/java/android/view/ViewOverlay.java +++ b/core/java/android/view/ViewOverlay.java @@ -290,7 +290,11 @@ public class ViewOverlay { } } - public void invalidateChildFast(View child, final Rect dirty) { + /** + * @hide + */ + @Override + public void damageChild(View child, final Rect dirty) { if (mHostView != null) { // Note: This is not a "fast" invalidation. Would be nice to instead invalidate // using DisplayList properties and a dirty rect instead of causing a real @@ -309,9 +313,9 @@ public class ViewOverlay { * @hide */ @Override - protected ViewParent invalidateChildInParentFast(int left, int top, Rect dirty) { + protected ViewParent damageChildInParent(int left, int top, Rect dirty) { if (mHostView instanceof ViewGroup) { - return ((ViewGroup) mHostView).invalidateChildInParentFast(left, top, dirty); + return ((ViewGroup) mHostView).damageChildInParent(left, top, dirty); } return null; } diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java index bbae0ca..6b21451 100644 --- a/core/java/android/view/ViewPropertyAnimator.java +++ b/core/java/android/view/ViewPropertyAnimator.java @@ -928,48 +928,38 @@ public class ViewPropertyAnimator { final RenderNode renderNode = mView.mRenderNode; switch (propertyConstant) { case TRANSLATION_X: - info.mTranslationX = value; - if (renderNode != null) renderNode.setTranslationX(value); + renderNode.setTranslationX(value); break; case TRANSLATION_Y: - info.mTranslationY = value; - if (renderNode != null) renderNode.setTranslationY(value); + renderNode.setTranslationY(value); break; case TRANSLATION_Z: - info.mTranslationZ = value; - if (renderNode != null) renderNode.setTranslationZ(value); + renderNode.setTranslationZ(value); break; case ROTATION: - info.mRotation = value; - if (renderNode != null) renderNode.setRotation(value); + renderNode.setRotation(value); break; case ROTATION_X: - info.mRotationX = value; - if (renderNode != null) renderNode.setRotationX(value); + renderNode.setRotationX(value); break; case ROTATION_Y: - info.mRotationY = value; - if (renderNode != null) renderNode.setRotationY(value); + renderNode.setRotationY(value); break; case SCALE_X: - info.mScaleX = value; - if (renderNode != null) renderNode.setScaleX(value); + renderNode.setScaleX(value); break; case SCALE_Y: - info.mScaleY = value; - if (renderNode != null) renderNode.setScaleY(value); + renderNode.setScaleY(value); break; case X: - info.mTranslationX = value - mView.mLeft; - if (renderNode != null) renderNode.setTranslationX(value - mView.mLeft); + renderNode.setTranslationX(value - mView.mLeft); break; case Y: - info.mTranslationY = value - mView.mTop; - if (renderNode != null) renderNode.setTranslationY(value - mView.mTop); + renderNode.setTranslationY(value - mView.mTop); break; case ALPHA: info.mAlpha = value; - if (renderNode != null) renderNode.setAlpha(value); + renderNode.setAlpha(value); break; } } @@ -981,30 +971,30 @@ public class ViewPropertyAnimator { * @return float The value of the named property */ private float getValue(int propertyConstant) { - final View.TransformationInfo info = mView.mTransformationInfo; + final RenderNode node = mView.mRenderNode; switch (propertyConstant) { case TRANSLATION_X: - return info.mTranslationX; + return node.getTranslationX(); case TRANSLATION_Y: - return info.mTranslationY; + return node.getTranslationY(); case TRANSLATION_Z: - return info.mTranslationZ; + return node.getTranslationZ(); case ROTATION: - return info.mRotation; + return node.getRotation(); case ROTATION_X: - return info.mRotationX; + return node.getRotationX(); case ROTATION_Y: - return info.mRotationY; + return node.getRotationY(); case SCALE_X: - return info.mScaleX; + return node.getScaleX(); case SCALE_Y: - return info.mScaleY; + return node.getScaleY(); case X: - return mView.mLeft + info.mTranslationX; + return mView.mLeft + node.getTranslationX(); case Y: - return mView.mTop + info.mTranslationY; + return mView.mTop + node.getTranslationY(); case ALPHA: - return info.mAlpha; + return mView.mTransformationInfo.mAlpha; } return 0; } @@ -1123,7 +1113,6 @@ public class ViewPropertyAnimator { } } if ((propertyMask & TRANSFORM_MASK) != 0) { - mView.mTransformationInfo.mMatrixDirty = true; if (!useRenderNodeProperties) { mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 687036c..5e4c143 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5163,12 +5163,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int width = mRight - mLeft; final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight(); final float dx = mLayout.getLineRight(0) - (width - padding); - canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); } if (mMarquee != null && mMarquee.isRunning()) { final float dx = -mMarquee.getScroll(); - canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); } } @@ -5182,8 +5182,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (mMarquee != null && mMarquee.shouldDrawGhost()) { - final int dx = (int) mMarquee.getGhostOffset(); - canvas.translate(isLayoutRtl ? -dx : dx, 0.0f); + final float dx = mMarquee.getGhostOffset(); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical); } diff --git a/core/java/android/widget/TimePickerDelegate.java b/core/java/android/widget/TimePickerDelegate.java index c9a9894..79256e5 100644 --- a/core/java/android/widget/TimePickerDelegate.java +++ b/core/java/android/widget/TimePickerDelegate.java @@ -152,11 +152,11 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement final int headerBackgroundColor = a.getColor( R.styleable.TimePicker_headerBackgroundColor, 0); - a.recycle(); - final int layoutResourceId = a.getResourceId( R.styleable.TimePicker_internalLayout, R.layout.time_picker_holo); + a.recycle(); + final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index cc51a8b..80e1caa 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -174,7 +174,6 @@ public class ActionBarImpl extends ActionBar { } private void init(View decor) { - mContext = decor.getContext(); mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById( com.android.internal.R.id.action_bar_overlay_layout); if (mOverlayLayout != null) { @@ -193,6 +192,7 @@ public class ActionBarImpl extends ActionBar { "with a compatible window decor layout"); } + mContext = mActionView.getContext(); mActionView.setContextView(mContextView); mContextDisplayMode = mActionView.isSplitActionBar() ? CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL; diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 39636fe..4c11fa9 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -574,6 +574,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUptime = in.readLong(); mPastUptime = in.readLong(); mUptimeStart = in.readLong(); + mRealtime = in.readLong(); mPastRealtime = in.readLong(); mRealtimeStart = in.readLong(); mUnpluggedUptime = in.readLong(); @@ -586,6 +587,7 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(mUptime); out.writeLong(runningUptime); out.writeLong(mUptimeStart); + out.writeLong(mRealtime); out.writeLong(runningRealtime); out.writeLong(mRealtimeStart); out.writeLong(mUnpluggedUptime); diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 6afeb86..4759451 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -229,9 +229,10 @@ int register_com_android_internal_os_RuntimeInit(JNIEnv* env) /*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL; - -AndroidRuntime::AndroidRuntime() : - mExitWithoutCleanup(false) +AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) : + mExitWithoutCleanup(false), + mArgBlockStart(argBlockStart), + mArgBlockLength(argBlockLength) { SkGraphics::Init(); // this sets our preference for 16bit images during decode @@ -266,6 +267,10 @@ AndroidRuntime::~AndroidRuntime() return jniRegisterNativeMethods(env, className, gMethods, numMethods); } +void AndroidRuntime::setArgv0(const char* argv0) { + strlcpy(mArgBlockStart, argv0, mArgBlockLength); +} + status_t AndroidRuntime::callMain(const char* className, jclass clazz, int argc, const char* const argv[]) { diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index cbed99f..a4efed7 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -19,8 +19,8 @@ #include <utils/Log.h> #include <binder/IPCThreadState.h> -#include <binder/ProcessState.h> #include <binder/IServiceManager.h> +#include <cutils/process_name.h> #include <cutils/sched_policy.h> #include <utils/String8.h> #include <utils/Vector.h> @@ -385,7 +385,9 @@ void android_os_Process_setArgV0(JNIEnv* env, jobject clazz, jstring name) } if (name8.size() > 0) { - ProcessState::self()->setArgV0(name8.string()); + const char* procName = name8.string(); + set_process_name(procName); + AndroidRuntime::getRuntime()->setArgv0(procName); } } diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 3e359d4..d079349 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -69,7 +69,7 @@ static void android_view_RenderNode_destroyDisplayList(JNIEnv* env, } // ---------------------------------------------------------------------------- -// RenderProperties +// RenderProperties - setters // ---------------------------------------------------------------------------- static void android_view_RenderNode_setCaching(JNIEnv* env, @@ -209,22 +209,6 @@ static void android_view_RenderNode_setScaleY(JNIEnv* env, displayList->mutateStagingProperties().setScaleY(sy); } -static void android_view_RenderNode_setTransformationInfo(JNIEnv* env, - jobject clazz, jlong displayListPtr, float alpha, - float translationX, float translationY, float translationZ, - float rotation, float rotationX, float rotationY, float scaleX, float scaleY) { - RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); - displayList->mutateStagingProperties().setAlpha(alpha); - displayList->mutateStagingProperties().setTranslationX(translationX); - displayList->mutateStagingProperties().setTranslationY(translationY); - displayList->mutateStagingProperties().setTranslationZ(translationZ); - displayList->mutateStagingProperties().setRotation(rotation); - displayList->mutateStagingProperties().setRotationX(rotationX); - displayList->mutateStagingProperties().setRotationY(rotationY); - displayList->mutateStagingProperties().setScaleX(scaleX); - displayList->mutateStagingProperties().setScaleY(scaleY); -} - static void android_view_RenderNode_setPivotX(JNIEnv* env, jobject clazz, jlong displayListPtr, float px) { RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); @@ -286,6 +270,10 @@ static void android_view_RenderNode_offsetTopAndBottom(JNIEnv* env, displayList->mutateStagingProperties().offsetTopBottom(offset); } +// ---------------------------------------------------------------------------- +// RenderProperties - getters +// ---------------------------------------------------------------------------- + static jboolean android_view_RenderNode_hasOverlappingRendering(JNIEnv* env, jobject clazz, jlong displayListPtr) { RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); @@ -352,6 +340,12 @@ static jfloat android_view_RenderNode_getTranslationY(JNIEnv* env, return displayList->stagingProperties().getTranslationY(); } +static jfloat android_view_RenderNode_getTranslationZ(JNIEnv* env, + jobject clazz, jlong displayListPtr) { + RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); + return displayList->stagingProperties().getTranslationZ(); +} + static jfloat android_view_RenderNode_getRotation(JNIEnv* env, jobject clazz, jlong displayListPtr) { RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); @@ -370,6 +364,53 @@ static jfloat android_view_RenderNode_getRotationY(JNIEnv* env, return displayList->stagingProperties().getRotationY(); } +static jboolean android_view_RenderNode_isPivotExplicitlySet(JNIEnv* env, + jobject clazz, jlong displayListPtr) { + RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); + return displayList->stagingProperties().isPivotExplicitlySet(); +} + +static jboolean android_view_RenderNode_hasIdentityMatrix(JNIEnv* env, + jobject clazz, jlong displayListPtr) { + RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); + return displayList->stagingProperties().getMatrixFlags() == 0; +} + +// ---------------------------------------------------------------------------- +// RenderProperties - computed getters +// ---------------------------------------------------------------------------- + +static void android_view_RenderNode_getTransformMatrix(JNIEnv* env, + jobject clazz, jlong displayListPtr, jlong outMatrixPtr) { + RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); + SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr); + + displayList->mutateStagingProperties().updateMatrix(); + const SkMatrix* transformMatrix = displayList->stagingProperties().getTransformMatrix(); + + if (displayList->stagingProperties().getMatrixFlags() == TRANSLATION) { + outMatrix->setTranslate(displayList->stagingProperties().getTranslationX(), + displayList->stagingProperties().getTranslationY()); + } else if (transformMatrix) { + *outMatrix = *transformMatrix; + } else { + outMatrix->setIdentity(); + } +} + +static void android_view_RenderNode_getInverseTransformMatrix(JNIEnv* env, + jobject clazz, jlong displayListPtr, jlong outMatrixPtr) { + // load transform matrix + android_view_RenderNode_getTransformMatrix(env, clazz, displayListPtr, outMatrixPtr); + SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr); + + // return it inverted + if (!outMatrix->invert(outMatrix)) { + // failed to load inverse, pass back identity + outMatrix->setIdentity(); + } +} + static jfloat android_view_RenderNode_getPivotX(JNIEnv* env, jobject clazz, jlong displayListPtr) { RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); @@ -424,8 +465,6 @@ static JNINativeMethod gMethods[] = { { "nSetRotationY", "(JF)V", (void*) android_view_RenderNode_setRotationY }, { "nSetScaleX", "(JF)V", (void*) android_view_RenderNode_setScaleX }, { "nSetScaleY", "(JF)V", (void*) android_view_RenderNode_setScaleY }, - { "nSetTransformationInfo","(JFFFFFFFFF)V", - (void*) android_view_RenderNode_setTransformationInfo }, { "nSetPivotX", "(JF)V", (void*) android_view_RenderNode_setPivotX }, { "nSetPivotY", "(JF)V", (void*) android_view_RenderNode_setPivotY }, { "nSetCameraDistance", "(JF)V", (void*) android_view_RenderNode_setCameraDistance }, @@ -448,11 +487,18 @@ static JNINativeMethod gMethods[] = { { "nGetScaleY", "(J)F", (void*) android_view_RenderNode_getScaleY }, { "nGetTranslationX", "(J)F", (void*) android_view_RenderNode_getTranslationX }, { "nGetTranslationY", "(J)F", (void*) android_view_RenderNode_getTranslationY }, + { "nGetTranslationZ", "(J)F", (void*) android_view_RenderNode_getTranslationZ }, { "nGetRotation", "(J)F", (void*) android_view_RenderNode_getRotation }, { "nGetRotationX", "(J)F", (void*) android_view_RenderNode_getRotationX }, { "nGetRotationY", "(J)F", (void*) android_view_RenderNode_getRotationY }, - { "nGetPivotX", "(J)F", (void*) android_view_RenderNode_getPivotX }, - { "nGetPivotY", "(J)F", (void*) android_view_RenderNode_getPivotY }, + { "nIsPivotExplicitlySet", "(J)Z", (void*) android_view_RenderNode_isPivotExplicitlySet }, + { "nHasIdentityMatrix", "(J)Z", (void*) android_view_RenderNode_hasIdentityMatrix }, + + { "nGetTransformMatrix", "(JJ)V", (void*) android_view_RenderNode_getTransformMatrix }, + { "nGetInverseTransformMatrix","(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix }, + + { "nGetPivotX", "(J)F", (void*) android_view_RenderNode_getPivotX }, + { "nGetPivotY", "(J)F", (void*) android_view_RenderNode_getPivotY }, #endif }; diff --git a/core/res/res/drawable/item_background_quantum.xml b/core/res/res/drawable/item_background_quantum.xml index f668ca0..11e1f67 100644 --- a/core/res/res/drawable/item_background_quantum.xml +++ b/core/res/res/drawable/item_background_quantum.xml @@ -15,4 +15,5 @@ --> <touch-feedback xmlns:android="http://schemas.android.com/apk/res/android" - android:tint="?attr/colorButtonPressed" /> + android:tint="?attr/colorButtonPressed" + android:pinned="true" /> diff --git a/core/res/res/layout/alert_dialog_quantum.xml b/core/res/res/layout/alert_dialog_quantum.xml index 4cc76ca..59dba08 100644 --- a/core/res/res/layout/alert_dialog_quantum.xml +++ b/core/res/res/layout/alert_dialog_quantum.xml @@ -20,33 +20,26 @@ android:id="@+id/parentPanel" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="8dip" - android:layout_marginEnd="8dip" android:orientation="vertical"> <LinearLayout android:id="@+id/topPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> - <View android:id="@+id/titleDividerTop" - android:layout_width="match_parent" - android:layout_height="2dip" - android:visibility="gone" - android:background="@android:color/holo_blue_light" /> <LinearLayout android:id="@+id/title_template" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical|start" - android:minHeight="@dimen/alert_dialog_title_height" - android:layout_marginStart="16dip" - android:layout_marginEnd="16dip"> + android:paddingStart="16dip" + android:paddingEnd="16dip" + android:paddingTop="16dip"> <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingEnd="8dip" android:src="@null" /> - <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle" + <TextView android:id="@+id/alertTitle" style="?android:attr/windowTitleStyle" android:singleLine="true" android:ellipsize="end" @@ -54,11 +47,6 @@ android:layout_height="wrap_content" android:textAlignment="viewStart" /> </LinearLayout> - <View android:id="@+id/titleDivider" - android:layout_width="match_parent" - android:layout_height="2dip" - android:visibility="gone" - android:background="@android:color/holo_blue_light" /> <!-- If the client uses a customTitle, it will be added here. --> </LinearLayout> @@ -78,8 +66,7 @@ android:layout_height="wrap_content" android:paddingStart="16dip" android:paddingEnd="16dip" - android:paddingTop="8dip" - android:paddingBottom="8dip"/> + android:paddingTop="16dip" /> </ScrollView> </LinearLayout> @@ -98,7 +85,7 @@ android:layout_height="wrap_content" android:minHeight="@dimen/alert_dialog_button_bar_height" android:orientation="vertical" - android:dividerPadding="0dip"> + android:padding="16dip"> <LinearLayout style="?android:attr/buttonBarStyle" android:layout_width="match_parent" @@ -106,33 +93,33 @@ android:orientation="horizontal" android:layoutDirection="locale" android:measureWithLargestChild="true"> - <Button android:id="@+id/button2" + <Button android:id="@+id/button3" android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="start" - android:layout_weight="1" + android:layout_marginRight="8dip" android:maxLines="2" - style="?android:attr/buttonBarButtonStyle" - android:textSize="14sp" android:minHeight="@dimen/alert_dialog_button_bar_height" - android:layout_height="wrap_content" /> - <Button android:id="@+id/button3" - android:layout_width="wrap_content" - android:layout_gravity="center_horizontal" + style="?android:attr/buttonBarButtonStyle" /> + <View android:layout_width="0dp" + android:layout_height="0dp" android:layout_weight="1" + android:visibility="invisible" /> + <Button android:id="@+id/button2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + android:layout_marginRight="8dip" android:maxLines="2" - style="?android:attr/buttonBarButtonStyle" - android:textSize="14sp" android:minHeight="@dimen/alert_dialog_button_bar_height" - android:layout_height="wrap_content" /> + style="?android:attr/buttonBarButtonStyle" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="end" - android:layout_weight="1" android:maxLines="2" android:minHeight="@dimen/alert_dialog_button_bar_height" - style="?android:attr/buttonBarButtonStyle" - android:textSize="14sp" - android:layout_height="wrap_content" /> + style="?android:attr/buttonBarButtonStyle" /> </LinearLayout> </LinearLayout> </LinearLayout> diff --git a/core/res/res/layout/dialog_custom_title_quantum.xml b/core/res/res/layout/dialog_custom_title_quantum.xml new file mode 100644 index 0000000..f8a2bf7 --- /dev/null +++ b/core/res/res/layout/dialog_custom_title_quantum.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- +This is a custom layout for a dialog. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:fitsSystemWindows="true"> + <FrameLayout android:id="@android:id/title_container" + android:layout_width="match_parent" + android:layout_height="@dimen/alert_dialog_title_height" + android:layout_weight="0" + android:gravity="center_vertical|start" + style="?android:attr/windowTitleBackgroundStyle"> + </FrameLayout> + <View android:id="@+id/titleDivider" + android:layout_width="match_parent" + android:layout_height="2dip" + android:background="@android:color/holo_blue_light" /> + <FrameLayout + android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_weight="1" + android:orientation="vertical" + android:foreground="?android:attr/windowContentOverlay"> + <FrameLayout android:id="@android:id/content" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + </FrameLayout> +</LinearLayout> diff --git a/core/res/res/layout/dialog_title_icons_quantum.xml b/core/res/res/layout/dialog_title_icons_quantum.xml new file mode 100644 index 0000000..e3d771c --- /dev/null +++ b/core/res/res/layout/dialog_title_icons_quantum.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- +This is an optimized layout for a screen, with the minimum set of features +enabled. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:fitsSystemWindows="true"> + + <LinearLayout android:id="@+id/title_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="center_vertical" + android:minHeight="@android:dimen/alert_dialog_title_height" + android:paddingStart="16dip" + android:paddingEnd="16dip"> + <ImageView android:id="@+id/left_icon" + android:layout_width="32dip" + android:layout_height="32dip" + android:scaleType="fitCenter" + android:layout_marginEnd="8dip" /> + <TextView android:id="@android:id/title" + style="?android:attr/windowTitleStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" /> + <ImageView android:id="@+id/right_icon" + android:layout_width="32dip" + android:layout_height="32dip" + android:scaleType="fitCenter" + android:layout_marginStart="8dip" /> + </LinearLayout> + + <View android:id="@+id/titleDivider" + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="@android:color/holo_blue_light" /> + + <FrameLayout + android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_weight="1" + android:orientation="vertical" + android:foreground="?android:attr/windowContentOverlay"> + <FrameLayout android:id="@android:id/content" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + </FrameLayout> +</LinearLayout> diff --git a/core/res/res/layout/dialog_title_quantum.xml b/core/res/res/layout/dialog_title_quantum.xml new file mode 100644 index 0000000..0a692ee --- /dev/null +++ b/core/res/res/layout/dialog_title_quantum.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +This is an optimized layout for a screen, with the minimum set of features +enabled. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:fitsSystemWindows="true"> + <TextView android:id="@android:id/title" style="?android:attr/windowTitleStyle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@android:dimen/alert_dialog_title_height" + android:paddingStart="16dip" + android:paddingEnd="16dip" + android:gravity="center_vertical|start" /> + <View android:id="@+id/titleDivider" + android:layout_width="match_parent" + android:layout_height="2dip" + android:background="@android:color/holo_blue_light" /> + <FrameLayout + android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_weight="1" + android:orientation="vertical" + android:foreground="?android:attr/windowContentOverlay"> + <FrameLayout android:id="@android:id/content" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + </FrameLayout> +</LinearLayout> diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml index 3265736..b1afec1 100644 --- a/core/res/res/layout/screen_action_bar.xml +++ b/core/res/res/layout/screen_action_bar.xml @@ -24,7 +24,7 @@ This is an optimized layout for a screen with the Action Bar enabled. android:layout_width="match_parent" android:layout_height="match_parent" android:splitMotionEvents="false" - android:theme="?attr/actionBarTheme"> + android:theme="?attr/actionBarWidgetTheme"> <FrameLayout android:id="@android:id/content" android:layout_width="match_parent" android:layout_height="match_parent" /> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 4d43831..aa5005f 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -677,8 +677,6 @@ <!-- Action bar styles --> <!-- =================== --> <eat-comment /> - <!-- Theme override for the Action Bar --> - <attr name="actionBarTheme" format="reference" /> <!-- Default style for tabs within an action bar --> <attr name="actionBarTabStyle" format="reference" /> <attr name="actionBarTabBarStyle" format="reference" /> @@ -4556,6 +4554,7 @@ <enum name="state_activated" value="8" /> <enum name="state_window_focused" value="9" /> </attr> + <attr name="versionCode" /> </declare-styleable> <!-- Define the virtual size of the drawing surface paths will draw to. --> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 39b8a6b..b14453a 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -866,6 +866,18 @@ <!-- The name of the logical parent of the activity as it appears in the manifest. --> <attr name="parentActivityName" format="string" /> + <!-- Define an activity that will persist across reboots. If such an activity is in the + Recents list when the device is shut off it will appear in the Recents list when + the device is next powered on. To be persisted all activities in the task from the + root activity up to the last activity before a <em>break</em> must be declared with + the persistable attribute. A <em>break</em> is the first activity after the root + started with Intent.FLAG_CLEAR_TASK_WHEN_RESET. + + <p>Activities that are declared with the persistable attribute will be provided with a + forced-persistable Bundle in onCreate() and onSavedInstanceState(), and must only + be passed a persistable Bundle in their Intent.extras. --> + <attr name="persistable" format="boolean" /> + <!-- The <code>manifest</code> tag is the root of an <code>AndroidManifest.xml</code> file, describing the contents of an Android package (.apk) file. One @@ -1528,6 +1540,7 @@ <!-- @hide This broacast receiver will only receive broadcasts for the primary user. Can only be used with receivers. --> <attr name="primaryUserOnly" format="boolean" /> + <attr name="persistable" /> </declare-styleable> <!-- The <code>activity-alias</code> tag declares a new diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index d4692f1..667adde 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2142,6 +2142,7 @@ <public type="attr" name="colorButtonPressed" /> <public type="attr" name="colorButtonNormalColored" /> <public type="attr" name="colorButtonPressedColored" /> + <public type="attr" name="persistable" /> <public-padding type="dimen" name="l_resource_pad" end="0x01050010" /> @@ -2181,9 +2182,13 @@ <public type="style" name="TextAppearance.Quantum.Widget" /> <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Menu" /> <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Subtitle" /> + <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse" /> <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Title" /> + <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse" /> <public type="style" name="TextAppearance.Quantum.Widget.ActionMode.Subtitle" /> + <public type="style" name="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse" /> <public type="style" name="TextAppearance.Quantum.Widget.ActionMode.Title" /> + <public type="style" name="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse" /> <public type="style" name="TextAppearance.Quantum.Widget.Button" /> <public type="style" name="TextAppearance.Quantum.Widget.DropDownHint" /> <public type="style" name="TextAppearance.Quantum.Widget.DropDownItem" /> diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml index 84a1ca4..85d8761 100644 --- a/core/res/res/values/styles_quantum.xml +++ b/core/res/res/values/styles_quantum.xml @@ -394,6 +394,7 @@ please see styles_device_defaults.xml. <style name="Widget.Quantum.Button" parent="Widget.Button"> <item name="background">@drawable/btn_default_quantum</item> <item name="textAppearance">?attr/textAppearanceButton</item> + <item name="textColor">?attr/textColorPrimary</item> <item name="minHeight">48dip</item> <item name="minWidth">96dip</item> </style> @@ -443,23 +444,13 @@ please see styles_device_defaults.xml. </style> <style name="Widget.Quantum.ButtonBar"> - <item name="paddingTop">0dip</item> - <item name="paddingStart">0dip</item> - <item name="paddingEnd">0dip</item> - <item name="paddingBottom">0dip</item> - <item name="divider">?attr/dividerVertical</item> - <item name="showDividers">middle</item> - <item name="dividerPadding">12dip</item> <item name="background">@null</item> </style> <style name="Widget.Quantum.ButtonBar.AlertDialog"> <item name="background">@null</item> - <item name="dividerPadding">0dp</item> </style> - <style name="Widget.Quantum.ButtonBar.Button"/> - <style name="Widget.Quantum.SegmentedButton" parent="SegmentedButton"> <item name="background">@drawable/btn_group_holo_dark</item> </style> @@ -740,7 +731,7 @@ please see styles_device_defaults.xml. <item name="contentDescription">@string/action_menu_overflow_description</item> </style> - <style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar.Button"/> + <style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar"/> <style name="Widget.Quantum.ActionBar.TabView" parent="Widget.ActionBar.TabView"> <item name="background">@drawable/tab_indicator_quantum</item> @@ -1063,8 +1054,7 @@ please see styles_device_defaults.xml. <style name="WindowTitle.Quantum"> <item name="singleLine">true</item> <item name="textAppearance">@style/TextAppearance.Quantum.WindowTitle</item> - <item name="shadowColor">#BB000000</item> - <item name="shadowRadius">2.75</item> + <item name="shadowRadius">0</item> </style> <style name="DialogWindowTitle.Quantum"> diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml index d39a1f86..50f1ca6 100644 --- a/core/res/res/values/themes_quantum.xml +++ b/core/res/res/values/themes_quantum.xml @@ -154,7 +154,7 @@ please see themes_device_defaults.xml. <item name="windowTitleStyle">@style/WindowTitle.Quantum</item> <item name="windowTitleSize">25dip</item> <item name="windowTitleBackgroundStyle">@style/WindowTitleBackground.Quantum</item> - <item name="windowContentTransitions">true</item> + <item name="windowContentTransitions">false</item> <item name="windowAnimationStyle">@style/Animation.Quantum.Activity</item> <item name="windowSoftInputMode">stateUnspecified|adjustUnspecified</item> <item name="windowActionBar">true</item> @@ -162,9 +162,9 @@ please see themes_device_defaults.xml. <!-- Dialog attributes --> <item name="dialogTheme">@style/Theme.Quantum.Dialog</item> - <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item> - <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item> - <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item> + <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_quantum</item> + <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_quantum</item> + <item name="dialogTitleDecorLayout">@layout/dialog_title_quantum</item> <!-- AlertDialog attributes --> <item name="alertDialogTheme">@style/Theme.Quantum.Dialog.Alert</item> @@ -488,9 +488,9 @@ please see themes_device_defaults.xml. <!-- Dialog attributes --> <item name="dialogTheme">@style/Theme.Quantum.Light.Dialog</item> - <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item> - <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item> - <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item> + <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_quantum</item> + <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_quantum</item> + <item name="dialogTitleDecorLayout">@layout/dialog_title_quantum</item> <!-- AlertDialog attributes --> <item name="alertDialogTheme">@style/Theme.Quantum.Light.Dialog.Alert</item> @@ -694,7 +694,7 @@ please see themes_device_defaults.xml. with an inverse color profile. The dark action bar sharply stands out against the light content. --> <style name="Theme.Quantum.Light.DarkActionBar"> - <item name="actionBarTheme">@style/Theme.Quantum</item> + <item name="actionBarWidgetTheme">@style/Theme.Quantum</item> </style> <!-- Variant of the quantum (dark) theme with no action bar. --> diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 73d5b74..0a234aa 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -368,7 +368,10 @@ <span class="en">Media Playback</span></a> </li> <li><a href="<?cs var:toroot ?>guide/topics/media/mediarouter.html"> - <span class="en">MediaRouter</span></a> + <span class="en">Media Router</span></a> + </li> + <li><a href="<?cs var:toroot ?>guide/topics/media/mediarouteprovider.html"> + <span class="en">Media Route Provider</span></a> </li> <li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html"> <span class="en">Supported Media Formats</span></a> diff --git a/docs/html/guide/topics/media/mediarouteprovider.jd b/docs/html/guide/topics/media/mediarouteprovider.jd new file mode 100644 index 0000000..389fbfb --- /dev/null +++ b/docs/html/guide/topics/media/mediarouteprovider.jd @@ -0,0 +1,453 @@ +page.title=Media Route Provider +page.tags="mediarouteprovider","mediacontrolintent" +@jd:body + +<div id="qv-wrapper"> + <div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#overview">Overview</a> + <ol> + <li><a href="#dist">Distribution of route providers</a></li> + <li><a href="#playback-types">Types of playback</a></li> + <li><a href="#mr-packages">Media router packages</a></li> + </ol> + </li> + <li><a href="#provider-service">Creating a Provider Service</a></li> + <li><a href="#route-caps">Specifying Route Capabilities</a> + <ol> + <li><a href="#route-cat">Route categories</a></li> + <li><a href="#media-types">Media types and protocols</a></li> + <li><a href="#playback-ctrls">Playback controls</a></li> + <li><a href="#mrpd">MediaRouteProviderDescriptor</a></li> + </ol> + </li> + <li><a href="#ctrl-routes">Controlling Routes</a></li> + </ol> + <h2>Key Classes</h2> + <ol> + <li>{@link android.support.v7.media.MediaRouteProvider}</li> + <li>{@link android.support.v7.media.MediaRouteProviderDescriptor}</li> + <li>{@link android.support.v7.media.MediaRouteProvider.RouteController RouteController}</li> + </ol> + <h2>Related Samples</h2> + <ol> + <li><a href="{@docRoot}samples/MediaRouter/index.html">MediaRouter</a></li> + </ol> + </div> +</div> + +<p>Users want to play media content from their Android devices bigger, brighter, and louder on + connected playback devices such as televisions, stereos, + and home theater equipment. As a manufacturer of these devices, allowing Android users to + instantly show a picture, play a song, or share a video for friends and family using your product + can make it much more compelling and engaging.</p> + +<p>The Android media router framework allows manufacturers to enable playback on their devices + through a standardized interface called a {@link android.support.v7.media.MediaRouteProvider}. + A route provider defines a common interface for playing media on a receiver device, making it + possible to play media on your equipment from any Android application that supports media + routes.</p> + +<p>This guide discusses how to create a media route provider for a receiver device and make it + available to other media playback applications that run on Android.</p> + +<h2 id="overview">Overview</h2> + +<p>The Android media router framework enables media app developers and media playback device + manufacturers to connect through a common API and common user interface. App developers that + implement a {@link android.support.v7.media.MediaRouter} interface can then connect to the + framework and play content to devices that participate in the media router framework. Media + playback device manufacturers can participate in the framework by publishing a {@link + android.support.v7.media.MediaRouteProvider} that allows other applications to connect to and + play media on the receiver devices. Figure 1 illustrates how an app connects to a receiving + device through the media router framework.</p> + +<img src="{@docRoot}images/mediarouter/media-route-provider-framework.png" alt="" id="figure1"/> +<p class="img-caption"> + <strong>Figure 1.</strong> Overview of how media route provider classes provide communication + from a media app to a receiver device. +</p> + +<p>When you build a media route provider for your receiver device, the provider serves the +following purposes:</p> + +<ul> + <li>Describe and publish the capabilities of the receiver device so other apps can discover it + and use its playback features.</li> + <li>Wrap the programming interface of the receiver device and its communication + transport mechanisms to make the device compatible with the media router framework.</li> +</ul> + + +<h3 id="dist">Distribution of route providers</h3> + +<p>A media route provider is distributed as part of an Android app. Your route provider can be + made available to other apps by extending + {@link android.support.v7.media.MediaRouteProviderService} or wrapping your implementation of + {@link android.support.v7.media.MediaRouteProvider} with your own service and declaring an intent + filter for the media route provider. These steps allow other apps to discover and make use of + your media route.</p> + +<p> + <strong>Note:</strong> The app containing the media route provider can also include a + <a href="{@docRoot}guide/topics/media/mediarouter.html">MediaRouter</a> interface to the + route provider, but this is not required. +</p> + + +<h3 id="playback-types">Types of playback</h3> + +<p>There are two main types of playback supported by the media router framework. A media route + provider can support one or both types of playback, depending on the capabilities of your playback + equipment and the functionality you want to support:</p> + +<ul> + <li><strong>Remote Playback</strong> — This approach uses the receiver device to handle the + content data retrieval, decoding, and playback, while an Android device in the user's hand is + used as a remote control. This approach is used by Android apps that support + <a href="https://developers.google.com/cast/">Google Cast</a>.</li> + <li><strong>Secondary Output</strong> — With this approach, the Android media application + retrieves, renders and streams video or music directly to the receiver device. This approach is + used to support Wireless Display output on Android.</li> +</ul> + + +<h3 id="mr-packages">Media router packages</h3> + +<p> + The media router APIs are provided as part of the Android Support Library version 18 and higher, + in the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a> + support library. You should use the classes in the + {@link android.support.v7.media} package for media route provider functions. + These APIs are compatible with devices running Android 2.1 (API level 7) and higher. +</p> + +<p class="caution"> + <strong>Caution:</strong> There is another set of media router APIs provided in the + {@link android.media} class package that have been superseded by the + <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a> + support library. You <em>should not</em> use the {@link android.media} classes for + implementing media route provider functions. +</p> + +<p>In order to use the {@link android.support.v7.media} media router classes, you + must add the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter" + >v7-mediarouter support library package</a> to your app development project. For more + information on adding support libraries to your app development project, see + <a href="{@docRoot}tools/support-library/setup.html">Support Library Setup</a>. +</p> + + +<h2 id="provider-service">Creating a Provider Service</h2> + +<p>The media router framework must be able to discover and connect to your media route provider + to allow other applications to use your route. In order to do this, the media router framework + looks for apps that declare a media route provider intent action. When another app wants to + connect to your provider, the framework must be able to invoke and connect to it, so your provider + must be encapsulated in a {@link android.app.Service}.</p> + +<p>The following example code shows the declaration of a media route provider service and the + intent filter in a manifest, which allows it to be discovered and used by the media router + framework:</p> + +<pre> +<service android:name=".provider.SampleMediaRouteProviderService" + android:label="@string/sample_media_route_provider_service" + android:process=":mrp"> + <intent-filter> + <action android:name="android.media.MediaRouteProviderService" /> + </intent-filter> +</service> +</pre> + +<p>This manifest example declares a service that wraps the actual media route provider classes. + The Android media router framework provides the + {@link android.support.v7.media.MediaRouteProviderService} class for use as a service wrapper for + media route providers. The following example code demonstrates how to use this wrapper + class:</p> + +<pre> +public class SampleMediaRouteProviderService extends MediaRouteProviderService { + + @Override + public MediaRouteProvider onCreateMediaRouteProvider() { + return new SampleMediaRouteProvider(this); + } +} +</pre> + + +<h2 id="route-caps">Specifying Route Capabilities</h2> + +<p>Apps connecting to the media router framework can discover your media route through your + app's manifest declarations, but they also need to know the capabilities of the media routes you + are providing. Media routes can be of different types and have different features, and other apps + need to be able to discover these details to determine if they are compatible with your route.</p> + +<p>The media router framework allows you to define and publish the capabilities of your media + route through {@link android.content.IntentFilter} objects, {@link + android.support.v7.media.MediaRouteDescriptor} objects and a {@link + android.support.v7.media.MediaRouteProviderDescriptor}. This section explains how to use these + classes to publish the details of your media route for other apps.</p> + + +<h3 id="route-cat">Route categories</h3> + +<p>As part of the programmatic description of your media route provider, you must specify + whether your provider supports remote playback, secondary output, or both. These are the route + categories provided by the media router framework:</p> + +<ul> + <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_AUDIO CATEGORY_LIVE_AUDIO} + — Output of audio to a secondary output device, such as a wireless-enabled music system. + </li> + <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_VIDEO CATEGORY_LIVE_VIDEO} + — Output of video to a secondary output device, such as Wireless Display devices.</li> + <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK + CATEGORY_REMOTE_PLAYBACK} — Play video or audio on a separate device which handles media + retrieval, decoding, and playback, such as + <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a> devices. + </li> +</ul> + +<p>In order to include these settings in a description of your media route, you insert them into + an {@link android.content.IntentFilter} object, which you later add to a + {@link android.support.v7.media.MediaRouteDescriptor} object:</p> + +<pre> +public final class SampleMediaRouteProvider extends MediaRouteProvider { + private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC; + static { + IntentFilter videoPlayback = new IntentFilter(); + <strong>videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);</strong> + CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>(); + CONTROL_FILTERS_BASIC.add(videoPlayback); + } +} + +</pre> + +<p>If you specify the {@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK + CATEGORY_REMOTE_PLAYBACK} intent, you must also define what media types and + playback controls are supported by your media route provider. The next section describes how to + specify these settings for your device.</p> + + +<h3 id="media-types">Media types and protocols</h3> + +<p>A media route provider for a remote playback device must specify the media types and transfer + protocols it supports. You specify these settings using the {@link android.content.IntentFilter} + class and the {@link android.content.IntentFilter#addDataScheme addDataScheme()} and + {@link android.content.IntentFilter#addDataType addDataType()} methods of that object. The + following code snippet demonstrates how to define an intent filter for supporting remote video + playback using http, https, and Real Time Streaming Protocol (RTSP):</p> + +<pre> +public final class SampleMediaRouteProvider extends MediaRouteProvider { + + private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC; + + static { + IntentFilter videoPlayback = new IntentFilter(); + videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); + videoPlayback.addAction(MediaControlIntent.ACTION_PLAY); + videoPlayback.addDataScheme("http"); + videoPlayback.addDataScheme("https"); + videoPlayback.addDataScheme("rtsp"); + addDataTypeUnchecked(videoPlayback, "video/*"); + CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>(); + CONTROL_FILTERS_BASIC.add(videoPlayback); + } + ... + + private static void addDataTypeUnchecked(IntentFilter filter, String type) { + try { + filter.addDataType(type); + } catch (MalformedMimeTypeException ex) { + throw new RuntimeException(ex); + } + } +} + +</pre> + + +<h3 id="playback-ctrls">Playback controls</h3> + +<p>A media route provider that offers remote playback must specify the types of media controls + it supports. These are the general types of control that media routes can provide:</p> + +<ul> + <li><strong>Playback controls</strong>, such as play, pause, rewind, and fast-forward.</li> + <li><strong>Queuing features</strong>, which allow the sending app to add and remove items + from a playlist which is maintained by the receiver device.</li> + <li><strong>Session features</strong>, which prevent sending apps from interfering with each + other by having the receiver device provide a session id to the requesting app and then checking + that id with each subsequent playback control request.</li> +</ul> + +<p>The following code example demonstrates how to construct an intent filter for supporting + basic media route playback controls:</p> + +<pre> +public final class SampleMediaRouteProvider extends MediaRouteProvider { + private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC; + static { + ... + IntentFilter playControls = new IntentFilter(); + playControls.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); + playControls.addAction(MediaControlIntent.ACTION_SEEK); + playControls.addAction(MediaControlIntent.ACTION_GET_STATUS); + playControls.addAction(MediaControlIntent.ACTION_PAUSE); + playControls.addAction(MediaControlIntent.ACTION_RESUME); + playControls.addAction(MediaControlIntent.ACTION_STOP); + CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>(); + CONTROL_FILTERS_BASIC.add(videoPlayback); + CONTROL_FILTERS_BASIC.add(playControls); + } + ... +} +</pre> + +<p>For more information about the available playback control intents, see the + {@link android.support.v7.media.MediaControlIntent} class.</p> + + +<h3 id="mrpd">MediaRouteProviderDescriptor</h3> + +<p>After defining the capabilities of your media route using {@link + android.content.IntentFilter} objects, you can then create a descriptor object for publishing to + the Android media router framework. This descriptor object contains the specifics of your media + route's capabilities so that other applications can determine how to interact with your media + route.</p> + +<p>The following example code demonstrates how to add the previously created intent filters to a + {@link android.support.v7.media.MediaRouteProviderDescriptor} and set the descriptor for use by + the media router framework:</p> + +<pre> +public SampleMediaRouteProvider(Context context) { + super(context); + publishRoutes(); +} + +private void publishRoutes() { + Resources r = getContext().getResources(); + // Create a route descriptor using previously created IntentFilters + MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder( + VARIABLE_VOLUME_BASIC_ROUTE_ID, + r.getString(R.string.variable_volume_basic_route_name)) + .setDescription(r.getString(R.string.sample_route_description)) + .addControlFilters(CONTROL_FILTERS_BASIC) + .setPlaybackStream(AudioManager.STREAM_MUSIC) + .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE) + .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) + .setVolumeMax(VOLUME_MAX) + .setVolume(mVolume) + .build(); + // Add the route descriptor to the provider descriptor + MediaRouteProviderDescriptor providerDescriptor = + new MediaRouteProviderDescriptor.Builder() + .addRoute(routeDescriptor) + .build(); + + // Publish the descriptor to the framework + setDescriptor(providerDescriptor); +} +</pre> + +<p>For more information on the available descriptor settings, see the reference documentation + for {@link android.support.v7.media.MediaRouteDescriptor} and {@link + android.support.v7.media.MediaRouteProviderDescriptor}.</p> + + +<h2 id="ctrl-routes">Controlling Routes</h2> + +<p>When an application connects to your media route provider, the provider receives playback + commands through the media router framework sent to your route by other apps. To handle these + requests, you must provide an implementation of a {@link + android.support.v7.media.MediaRouteProvider.RouteController} class, which processes the commands + and handles the actual communication to your receiver device.</p> + +<p>The media router framework calls the {@link + android.support.v7.media.MediaRouteProvider#onCreateRouteController onCreateRouteController()} + method of your route provider to obtain an instance of this class and then routes requests to it. + These are the key methods of the {@link + android.support.v7.media.MediaRouteProvider.RouteController} class, which you must implement for + your media route provider:</p> + +<ul> + <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSelect onSelect()} + — Called when an application selects your route for playback. You use this method to do + any preparation work that may be required before media playback begins.</li> + <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest + onControlRequest()} — Sends specific playback commands to the receiving device.</li> + <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSetVolume + onSetVolume()} — Sends a request to the receiving device to set the playback volume to a + specific value.</li> + <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUpdateVolume + onUpdateVolume()} — Sends a request to the receiving device to modify the playback + volume by a specified amount.</li> + <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUnselect + onUnselect()} — Called when an application unselects a route.</li> + <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onRelease onRelease()} + — Called when the route is no longer needed by the framework, allowing it to free its + resources.</li> +</ul> + +<p>All playback control requests, except for volume changes, are directed to the {@link + android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest onControlRequest()} + method. Your implementation of this method must parse the control requests and respond to them + appropriately. Here is an example implementation of this method which processes commands for a + remote playback media route:</p> + +<pre> +private final class SampleRouteController extends + MediaRouteProvider.RouteController { + ... + + @Override + public boolean onControlRequest(Intent intent, ControlRequestCallback callback) { + + String action = intent.getAction(); + + if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { + boolean success = false; + if (action.equals(MediaControlIntent.ACTION_PLAY)) { + success = handlePlay(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) { + success = handleEnqueue(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) { + success = handleRemove(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_SEEK)) { + success = handleSeek(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) { + success = handleGetStatus(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) { + success = handlePause(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_RESUME)) { + success = handleResume(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_STOP)) { + success = handleStop(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) { + success = handleStartSession(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) { + success = handleGetSessionStatus(intent, callback); + } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) { + success = handleEndSession(intent, callback); + } + + Log.d(TAG, mSessionManager.toString()); + return success; + } + return false; + } + ... +} +</pre> + +<p>It is important to understand that the {@link + android.support.v7.media.MediaRouteProvider.RouteController} class is intended to act as a wrapper + for the API to your media playback equipment. The implementation of the methods in this class is + entirely dependent on the programmatic interface provided by your receiving device.</p> diff --git a/docs/html/guide/topics/media/mediarouter.jd b/docs/html/guide/topics/media/mediarouter.jd index 1b10265..e0bf889 100644 --- a/docs/html/guide/topics/media/mediarouter.jd +++ b/docs/html/guide/topics/media/mediarouter.jd @@ -1,5 +1,5 @@ -page.title=MediaRouter -page.tags="cast","chromecast","wireless display","miracast" +page.title=Media Router +page.tags="mediarouter","cast","chromecast","wireless display","miracast" @jd:body <div id="qv-wrapper"> @@ -36,6 +36,10 @@ page.tags="cast","chromecast","wireless display","miracast" <li>{@link android.support.v7.media.MediaRouter.Callback}</li> <li>{@link android.support.v7.media.MediaRouteProvider}</li> </ol> + <h2>Related Samples</h2> + <ol> + <li><a href="{@docRoot}guide/topics/media/mediarouter.html">MediaRouter</a></li> + </ol> </div> </div> @@ -105,15 +109,17 @@ page.tags="cast","chromecast","wireless display","miracast" (API level 7) and higher. </p> -<p class="note"> - <strong>Note:</strong> There is another set of media router APIs provided in the +<p class="caution"> + <strong>Caution:</strong> There is another set of media router APIs provided in the {@link android.media} that have been superseded by the v7-mediarouter support library. You <em>should not</em> use the {@link android.media} classes for media router functions. </p> <p>In order to use the {@link android.support.v7.media} media router classes, you must add the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter - support library package</a> to your app development project. + support library package</a> to your app development project. For more + information on adding support libraries to your app development project, see + <a href="{@docRoot}tools/support-library/setup.html">Support Library Setup</a>. </p> @@ -211,9 +217,9 @@ page.tags="cast","chromecast","wireless display","miracast" CATEGORY_LIVE_VIDEO} — Output of video to a secondary output device, such as Wireless Display devices.</li> <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK - CATEGORY_REMOTE_PLAYBACK} — Play video or audio on a separate device that supports the - <a href="https://developers.google.com/cast/">Google Cast</a> remote control protocol, such - as <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a>. + CATEGORY_REMOTE_PLAYBACK} — Play video or audio on a separate device that handles media + retrieval, decoding, and playback, such as + <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a> devices. </li> </ul> @@ -279,7 +285,7 @@ public boolean onCreateOptionsMenu(Menu menu) { <p>In order to connect to a media route selected by the user, your app must obtain the {@link android.support.v7.media.MediaRouter} framework object and then attach a {@link android.support.v7.media.MediaRouter.Callback} object. The callback object receives messages - from the media router framework when a route selected, changed or disconnected by the user.</p> + from the media router framework when a route is selected, changed, or disconnected by the user.</p> <p>To obtain an instance of the {@link android.support.v7.media.MediaRouter} framework object, call {@link android.support.v7.media.MediaRouter#getInstance MediaRouter.getInstance()} @@ -299,11 +305,11 @@ public boolean onCreateOptionsMenu(Menu menu) { <p>The media router framework communicates with an app through a callback object that you attach to the {@link android.support.v7.media.MediaRouter} framework object. An app that uses the media router framework must extend the {@link - android.support.v7.media.MediaRouter.Callback} object to receive messages when a media route is - connected and provide content to the connected device through that route.</p> + android.support.v7.media.MediaRouter.Callback} object in order to receive messages when a + media route is connected.</p> -<p>There are several methods in the callback that can be overwritten to receive messages about - media router events. At the minimum, your implementation of the {@link +<p>There are several methods in the callback that you can override to receive information about + media router events. At minimum, your implementation of the {@link android.support.v7.media.MediaRouter.Callback} class should override the following methods:</p> @@ -440,12 +446,12 @@ public class MediaRouterPlaybackActivity extends ActionBarActivity { <p class="note"> <strong>Note:</strong> The media route framework also provides a - {@link android.support.v7.app.MediaRouteDiscoveryFragment} class which takes care of adding and - removing the call back for an activity. + {@link android.support.v7.app.MediaRouteDiscoveryFragment} class, which takes care of adding and + removing the callback for an activity. </p> <p>Now when you run your application, you should see a Cast button appear in your activity. - When you press the button the media router framework, a route selection dialog appears as shown + When you touch the button, a route selection dialog appears as shown in figure 3, allowing your user to select an available media route. Make sure you have a supported device available on your local network when testing this interface.</p> diff --git a/docs/html/images/mediarouter/media-route-provider-framework.png b/docs/html/images/mediarouter/media-route-provider-framework.png Binary files differnew file mode 100644 index 0000000..60cc29a --- /dev/null +++ b/docs/html/images/mediarouter/media-route-provider-framework.png diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist Binary files differnew file mode 100644 index 0000000..d82ea05 --- /dev/null +++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png Binary files differnew file mode 100644 index 0000000..3435e35 --- /dev/null +++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist Binary files differnew file mode 100644 index 0000000..07791df --- /dev/null +++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png Binary files differnew file mode 100644 index 0000000..d6e3e95 --- /dev/null +++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist Binary files differnew file mode 100644 index 0000000..ffd8212 --- /dev/null +++ b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png Binary files differnew file mode 100644 index 0000000..d6e3e95 --- /dev/null +++ b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index e320c67..1760458 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -121,20 +121,6 @@ import java.util.Arrays; * document.</p></div> */ public abstract class Drawable { - /** - * Hotspot identifier mask for tracking touch points. - * - * @hide until hotspot APIs are finalized - */ - public static final int HOTSPOT_TOUCH_MASK = 0xFF; - - /** - * Hotspot identifier for tracking keyboard focus. - * - * @hide until hotspot APIs are finalized - */ - public static final int HOTSPOT_FOCUS = 0x100; - private static final Rect ZERO_BOUNDS_RECT = new Rect(); private int[] mStateSet = StateSet.WILD_CARD; diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index f3dd2fc..33683ab 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -60,9 +60,11 @@ import java.util.HashSet; * The vector drawable has 6 elements: * <p/> * <dl> - * <dt><code><vector></code></dt><dd> - * The attribute <code>android:trigger</code> which defines a state change that + * <dt><code><vector></code></dt> + * <dd>The attribute <code>android:trigger</code> defines a state change that * will drive the animation </dd> + * <dd>The attribute <code>android:versionCode</code> defines the version of + * VectorDrawable </dd> * <dt><code><size></code></dt> * <dd>Used to defined the intrinsic Width Height size of the drawable using * <code>android:width</code> and <code>android:height</code> </dd> @@ -494,6 +496,16 @@ public class VectorDrawable extends Drawable { } else if (SHAPE_VECTOR.equals(tagName)) { TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable); animatedPath.setTrigger(a.getInteger(R.styleable.VectorDrawable_trigger, 0)); + + // Parsing the version information. + // Right now, we only support version "1". + // If the xml didn't specify the version number, the default version is "1". + int versionCode = a.getInt(R.styleable.VectorDrawable_versionCode, 1); + if (versionCode != 1) { + throw new IllegalArgumentException( + "So far, VectorDrawable only support version 1"); + } + a.recycle(); } } diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h index 649f4c3..6f2af90 100644 --- a/include/android_runtime/AndroidRuntime.h +++ b/include/android_runtime/AndroidRuntime.h @@ -34,7 +34,7 @@ namespace android { class AndroidRuntime { public: - AndroidRuntime(); + AndroidRuntime(char* argBlockStart, size_t argBlockSize); virtual ~AndroidRuntime(); enum StartMode { @@ -44,6 +44,8 @@ public: Tool, }; + void setArgv0(const char* argv0); + /** * Register a set of methods in the specified class. */ @@ -120,6 +122,8 @@ private: Vector<JavaVMOption> mOptions; bool mExitWithoutCleanup; + char* const mArgBlockStart; + const size_t mArgBlockLength; /* JNI JavaVM pointer */ static JavaVM* mJavaVM; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 34d98a1..663b67e 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -61,8 +61,12 @@ RenderNode::~RenderNode() { void RenderNode::destroyDisplayListDeferred(RenderNode* displayList) { if (displayList) { - DISPLAY_LIST_LOGD("Deferring display list destruction"); - Caches::getInstance().deleteDisplayListDeferred(displayList); + if (Caches::hasInstance()) { + DISPLAY_LIST_LOGD("Deferring display list destruction"); + Caches::getInstance().deleteDisplayListDeferred(displayList); + } else { + delete displayList; + } } } diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp index 3975a76..e7e7768 100644 --- a/libs/hwui/RenderProperties.cpp +++ b/libs/hwui/RenderProperties.cpp @@ -45,28 +45,24 @@ RenderProperties::PrimitiveFields::PrimitiveFields() , mPrevWidth(-1), mPrevHeight(-1) , mPivotExplicitlySet(false) , mMatrixDirty(false) - , mMatrixIsIdentity(true) , mMatrixFlags(0) , mCaching(false) { } RenderProperties::ComputedFields::ComputedFields() : mTransformMatrix(NULL) - , mTransformCamera(NULL) , mTransformMatrix3D(NULL) , mClipPath(NULL) { } RenderProperties::ComputedFields::~ComputedFields() { delete mTransformMatrix; - delete mTransformCamera; delete mTransformMatrix3D; delete mClipPath; } RenderProperties::RenderProperties() - : mCameraDistance(0) - , mStaticMatrix(NULL) + : mStaticMatrix(NULL) , mAnimationMatrix(NULL) { } @@ -82,9 +78,12 @@ RenderProperties& RenderProperties::operator=(const RenderProperties& other) { setAnimationMatrix(other.getAnimationMatrix()); setCameraDistance(other.getCameraDistance()); - // Update the computed fields - updateMatrix(); + // Update the computed clip path updateClipPath(); + + // Force recalculation of the matrix, since other's dirty bit may be clear + mPrimitiveFields.mMatrixDirty = true; + updateMatrix(); } return *this; } @@ -106,8 +105,8 @@ void RenderProperties::debugOutputProperties(const int level) const { ALOGD("%*sTranslate %.2f, %.2f, %.2f", level * 2, "", mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY, mPrimitiveFields.mTranslationZ); } else { - ALOGD("%*sConcatMatrix %p: " MATRIX_4_STRING, - level * 2, "", mComputedFields.mTransformMatrix, MATRIX_4_ARGS(mComputedFields.mTransformMatrix)); + ALOGD("%*sConcatMatrix %p: " SK_MATRIX_STRING, + level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix)); } } @@ -141,7 +140,7 @@ void RenderProperties::updateMatrix() { if (mPrimitiveFields.mMatrixFlags && mPrimitiveFields.mMatrixFlags != TRANSLATION) { if (!mComputedFields.mTransformMatrix) { // only allocate a mPrimitiveFields.matrix if we have a complex transform - mComputedFields.mTransformMatrix = new Matrix4(); + mComputedFields.mTransformMatrix = new SkMatrix(); } if (!mPrimitiveFields.mPivotExplicitlySet) { if (mPrimitiveFields.mWidth != mPrimitiveFields.mPrevWidth || mPrimitiveFields.mHeight != mPrimitiveFields.mPrevHeight) { @@ -153,33 +152,31 @@ void RenderProperties::updateMatrix() { } if ((mPrimitiveFields.mMatrixFlags & ROTATION_3D) == 0) { - mComputedFields.mTransformMatrix->loadTranslate( - mPrimitiveFields.mPivotX + mPrimitiveFields.mTranslationX, - mPrimitiveFields.mPivotY + mPrimitiveFields.mTranslationY, - 0); - mComputedFields.mTransformMatrix->rotate(mPrimitiveFields.mRotation, 0, 0, 1); - mComputedFields.mTransformMatrix->scale(mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, 1); - mComputedFields.mTransformMatrix->translate(-mPrimitiveFields.mPivotX, -mPrimitiveFields.mPivotY); + mComputedFields.mTransformMatrix->setTranslate( + mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY); + mComputedFields.mTransformMatrix->preRotate(mPrimitiveFields.mRotation, + mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY); + mComputedFields.mTransformMatrix->preScale( + mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, + mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY); } else { - if (!mComputedFields.mTransformCamera) { - mComputedFields.mTransformCamera = new Sk3DView(); + if (!mComputedFields.mTransformMatrix3D) { mComputedFields.mTransformMatrix3D = new SkMatrix(); } - SkMatrix transformMatrix; - transformMatrix.reset(); - mComputedFields.mTransformCamera->save(); - transformMatrix.preScale(mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY); - mComputedFields.mTransformCamera->rotateX(mPrimitiveFields.mRotationX); - mComputedFields.mTransformCamera->rotateY(mPrimitiveFields.mRotationY); - mComputedFields.mTransformCamera->rotateZ(-mPrimitiveFields.mRotation); - mComputedFields.mTransformCamera->getMatrix(mComputedFields.mTransformMatrix3D); + mComputedFields.mTransformMatrix->reset(); + mComputedFields.mTransformCamera.save(); + mComputedFields.mTransformMatrix->preScale( + mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, + mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY); + mComputedFields.mTransformCamera.rotateX(mPrimitiveFields.mRotationX); + mComputedFields.mTransformCamera.rotateY(mPrimitiveFields.mRotationY); + mComputedFields.mTransformCamera.rotateZ(-mPrimitiveFields.mRotation); + mComputedFields.mTransformCamera.getMatrix(mComputedFields.mTransformMatrix3D); mComputedFields.mTransformMatrix3D->preTranslate(-mPrimitiveFields.mPivotX, -mPrimitiveFields.mPivotY); mComputedFields.mTransformMatrix3D->postTranslate(mPrimitiveFields.mPivotX + mPrimitiveFields.mTranslationX, mPrimitiveFields.mPivotY + mPrimitiveFields.mTranslationY); - transformMatrix.postConcat(*mComputedFields.mTransformMatrix3D); - mComputedFields.mTransformCamera->restore(); - - mComputedFields.mTransformMatrix->load(transformMatrix); + mComputedFields.mTransformMatrix->postConcat(*mComputedFields.mTransformMatrix3D); + mComputedFields.mTransformCamera.restore(); } } mPrimitiveFields.mMatrixDirty = false; diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 061e469..dd68210 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -258,20 +258,20 @@ public: return mPrimitiveFields.mPivotY; } + bool isPivotExplicitlySet() const { + return mPrimitiveFields.mPivotExplicitlySet; + } + void setCameraDistance(float distance) { - if (distance != mCameraDistance) { - mCameraDistance = distance; + if (distance != getCameraDistance()) { mPrimitiveFields.mMatrixDirty = true; - if (!mComputedFields.mTransformCamera) { - mComputedFields.mTransformCamera = new Sk3DView(); - mComputedFields.mTransformMatrix3D = new SkMatrix(); - } - mComputedFields.mTransformCamera->setCameraLocation(0, 0, distance); + mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance); } } float getCameraDistance() const { - return mCameraDistance; + // TODO: update getCameraLocationZ() to be const + return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ(); } void setLeft(int left) { @@ -396,7 +396,7 @@ public: return mPrimitiveFields.mMatrixFlags; } - const Matrix4* getTransformMatrix() const { + const SkMatrix* getTransformMatrix() const { return mComputedFields.mTransformMatrix; } @@ -481,13 +481,11 @@ private: int mPrevWidth, mPrevHeight; bool mPivotExplicitlySet; bool mMatrixDirty; - bool mMatrixIsIdentity; uint32_t mMatrixFlags; bool mCaching; } mPrimitiveFields; // mCameraDistance isn't in mPrimitiveFields as it has a complex setter - float mCameraDistance; SkMatrix* mStaticMatrix; SkMatrix* mAnimationMatrix; @@ -502,11 +500,12 @@ private: * Stores the total transformation of the DisplayList based upon its scalar * translate/rotate/scale properties. * - * In the common translation-only case, the matrix isn't allocated and the mTranslation - * properties are used directly. + * In the common translation-only case, the matrix isn't necessarily allocated, + * and the mTranslation properties are used directly. */ - Matrix4* mTransformMatrix; - Sk3DView* mTransformCamera; + SkMatrix* mTransformMatrix; + + Sk3DView mTransformCamera; SkMatrix* mTransformMatrix3D; SkPath* mClipPath; // TODO: remove this, create new ops for efficient/special case clipping SkRegion::Op mClipPathOp; diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index cc6d0cd..5bdb18a 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -108,7 +108,7 @@ public: * Returns the current clip in local coordinates. The clip rect is * transformed by the inverse transform matrix. */ - const Rect& getLocalClip(); + ANDROID_API const Rect& getLocalClip(); /** * Resets the clip to the specified rect. diff --git a/packages/BackupRestoreConfirmation/AndroidManifest.xml b/packages/BackupRestoreConfirmation/AndroidManifest.xml index 4fb26ae..8141fa7 100644 --- a/packages/BackupRestoreConfirmation/AndroidManifest.xml +++ b/packages/BackupRestoreConfirmation/AndroidManifest.xml @@ -1,20 +1,21 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +/* + * Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ --> - <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.backupconfirm" > diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml index 179bcd1..6b77a7c 100644 --- a/packages/DocumentsUI/AndroidManifest.xml +++ b/packages/DocumentsUI/AndroidManifest.xml @@ -42,7 +42,7 @@ <activity android:name=".SettingsActivity" android:label="@string/menu_settings" - android:theme="@android:style/Theme.Holo.Light.DialogWhenLarge" + android:theme="@android:style/Theme.DeviceDefault.Light.DialogWhenLarge" android:exported="false" /> <provider diff --git a/packages/DocumentsUI/res/values-sw720dp/styles.xml b/packages/DocumentsUI/res/values-sw720dp/styles.xml index 19d2ebe..8d31444 100644 --- a/packages/DocumentsUI/res/values-sw720dp/styles.xml +++ b/packages/DocumentsUI/res/values-sw720dp/styles.xml @@ -15,11 +15,11 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android"> - <style name="Theme" parent="@android:style/Theme.Holo.Light"> + <style name="Theme" parent="@android:style/Theme.DeviceDefault.Light"> <item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item> <item name="android:windowBackground">@*android:drawable/dialog_full_holo_light</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:windowIsTranslucent">true</item> - <item name="android:windowAnimationStyle">@*android:style/Animation.Holo.Dialog</item> + <item name="android:windowAnimationStyle">@*android:style/Animation.DeviceDefault.Dialog</item> </style> </resources> diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml index 0c8f712..a416eb4 100644 --- a/packages/DocumentsUI/res/values/styles.xml +++ b/packages/DocumentsUI/res/values/styles.xml @@ -29,11 +29,11 @@ <!-- Normally just a redirection, but this is used to make ourselves a dialog on large tablets --> - <style name="Theme" parent="@android:style/Theme.Holo.Light"> + <style name="Theme" parent="@android:style/Theme.DeviceDefault.Light"> <item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item> </style> - <style name="DarkerOverflow" parent="@android:style/Widget.Holo.Light.ActionButton.Overflow"> + <style name="DarkerOverflow" parent="@android:style/Widget.DeviceDefault.Light.ActionButton.Overflow"> <item name="android:src">@drawable/ic_menu_overflow</item> </style> diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml index d4f98af..80fcf75 100644 --- a/packages/Keyguard/res/values/styles.xml +++ b/packages/Keyguard/res/values/styles.xml @@ -68,7 +68,7 @@ <item name="android:textSize">@dimen/widget_big_font_size</item> </style> - <style name="Widget.TransportControl.SeekBar" parent="@android:style/Widget.Holo.SeekBar"> + <style name="Widget.TransportControl.SeekBar" parent="@android:style/Widget.DeviceDefault.Light.SeekBar"> <item name="android:indeterminateOnly">false</item> <item name="android:progressDrawable">@drawable/scrubber_progress_horizontal_holo_light</item> <item name="android:indeterminateDrawable">@drawable/scrubber_progress_horizontal_holo_light</item> diff --git a/packages/Keyguard/test/AndroidManifest.xml b/packages/Keyguard/test/AndroidManifest.xml index b801e4b..1638127 100644 --- a/packages/Keyguard/test/AndroidManifest.xml +++ b/packages/Keyguard/test/AndroidManifest.xml @@ -23,7 +23,7 @@ <application android:label="@string/app_name" android:icon="@drawable/app_icon"> <activity android:name=".KeyguardTestActivity" android:label="@string/app_name" - android:theme="@android:style/Theme.Holo"> + android:theme="@android:style/Theme.DeviceDefault.Light"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml index 6fc77df..4488b6a 100644 --- a/packages/PrintSpooler/res/layout/select_printer_activity.xml +++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml @@ -61,7 +61,7 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:indeterminate="true" - style="@android:style/Widget.Holo.ProgressBar.Horizontal"> + style="@android:style/Widget.DeviceDefault.Light.ProgressBar.Horizontal"> </ProgressBar> </LinearLayout> diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml index 86f4a37..94ab895 100644 --- a/packages/PrintSpooler/res/values/themes.xml +++ b/packages/PrintSpooler/res/values/themes.xml @@ -16,7 +16,7 @@ <resources> - <style name="PrintJobConfigActivityTheme" parent="@android:style/Theme.Holo.Light.NoActionBar"> + <style name="PrintJobConfigActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowSoftInputMode">stateAlwaysHidden|adjustResize</item> <item name="android:windowIsTranslucent">true</item> @@ -25,11 +25,11 @@ <item name="android:windowIsFloating">true</item> </style> - <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.Holo.Light"> + <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.DeviceDefault.Light"> <item name="android:actionBarStyle">@style/SelectPrinterActivityActionBarStyle</item> </style> - <style name="SelectPrinterActivityActionBarStyle" parent="@android:style/Widget.Holo.ActionBar"> + <style name="SelectPrinterActivityActionBarStyle" parent="@android:style/Widget.DeviceDefault.Light.ActionBar"> <item name="android:displayOptions">showTitle</item> </style> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 29e8d1d..19286c8 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -1,3 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.shell" coreApp="true" @@ -83,7 +101,7 @@ <activity android:name=".BugreportWarningActivity" - android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true" android:exported="false" /> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index b09cc1d..3424eed 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -1,3 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" package="com.android.systemui" @@ -157,7 +175,7 @@ <activity android:name=".usb.UsbConfirmActivity" android:exported="true" android:permission="android.permission.MANAGE_USB" - android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true"> </activity> @@ -166,7 +184,7 @@ <activity android:name=".usb.UsbPermissionActivity" android:exported="true" android:permission="android.permission.MANAGE_USB" - android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true"> </activity> @@ -175,7 +193,7 @@ <activity android:name=".usb.UsbResolverActivity" android:exported="true" android:permission="android.permission.MANAGE_USB" - android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true"> </activity> @@ -184,7 +202,7 @@ <activity android:name=".usb.UsbAccessoryUriActivity" android:exported="true" android:permission="android.permission.MANAGE_USB" - android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true"> </activity> @@ -192,7 +210,7 @@ <!-- started from UsbDebuggingManager --> <activity android:name=".usb.UsbDebuggingActivity" android:permission="android.permission.MANAGE_USB" - android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true"> </activity> @@ -202,7 +220,7 @@ android:name=".net.NetworkOverLimitActivity" android:exported="true" android:permission="android.permission.MANAGE_NETWORK_POLICY" - android:theme="@android:style/Theme.Holo.Panel" + android:theme="@android:style/Theme.DeviceDefault.Light.Panel" android:finishOnCloseSystemDialogs="true" android:launchMode="singleTop" android:taskAffinity="com.android.systemui.net" diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 1da66bb..a7ec064 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -24,19 +24,10 @@ android:id="@+id/notification_panel" android:layout_width="0dp" android:layout_height="wrap_content" - android:background="@drawable/notification_panel_bg" android:paddingTop="@dimen/notification_panel_padding_top" android:layout_marginStart="@dimen/notification_panel_margin_left" > - <View - android:id="@+id/handle" - android:layout_width="match_parent" - android:layout_height="@dimen/close_handle_height" - android:background="@drawable/status_bar_close" - android:visibility="invisible" - /> - <include layout="@layout/carrier_label" android:layout_height="@dimen/carrier_label_height" @@ -69,6 +60,7 @@ /> <FrameLayout + android:id="@+id/notification_container_parent" android:layout_width="match_parent" android:layout_height="wrap_content" > @@ -77,21 +69,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> - - <ScrollView - android:id="@+id/scroll" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:fadingEdge="none" - android:overScrollMode="ifContentScrolls" - > - <com.android.systemui.statusbar.policy.NotificationRowLayout - android:id="@+id/latestItems" - android:layout_width="match_parent" - android:layout_height="wrap_content" - systemui:rowHeight="@dimen/notification_row_min_height" - /> - </ScrollView> <com.android.systemui.statusbar.stack.NotificationStackScrollLayout android:id="@+id/notification_stack_scroller" diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 14af020..76cadd7 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -16,12 +16,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android"> - <style name="RecentsStyle" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar"> + <style name="RecentsStyle" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar"> <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item> </style> <!-- Alternate Recents theme --> - <style name="RecentsTheme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar"> + <style name="RecentsTheme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">true</item> <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item> diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java index 90b0c49..1832d37 100644 --- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java @@ -34,6 +34,8 @@ import android.view.View.OnClickListener; import android.view.ViewConfiguration; import android.view.ViewGroup; +import com.android.systemui.statusbar.policy.ScrollAdapter; + public class ExpandHelper implements Gefingerpoken, OnClickListener { public interface Callback { View getChildAtRawPosition(float x, float y); @@ -609,19 +611,5 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener { } mVibrator.vibrate(duration, AudioManager.STREAM_SYSTEM); } - - public interface ScrollAdapter { - - /** - * @return Whether the view returned by {@link #getHostView()} is scrolled to the top - * and can therefore be expanded by a single finger drag - */ - public boolean isScrolledToTop(); - - /** - * @return The view in which the scrolling is performed - */ - public View getHostView(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java index d584043..c99f691 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java +++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java @@ -83,22 +83,7 @@ public class ToggleSlider extends RelativeLayout } public void onCheckedChanged(CompoundButton toggle, boolean checked) { - Drawable thumb; - Drawable slider; - final Resources res = getContext().getResources(); - if (checked) { - thumb = res.getDrawable( - com.android.internal.R.drawable.scrubber_control_disabled_holo); - slider = res.getDrawable( - R.drawable.status_bar_settings_slider_disabled); - } else { - thumb = res.getDrawable( - com.android.internal.R.drawable.scrubber_control_selector_holo); - slider = res.getDrawable( - com.android.internal.R.drawable.scrubber_progress_horizontal_holo_dark); - } - mSlider.setThumb(thumb); - mSlider.setProgressDrawable(slider); + mSlider.setEnabled(checked); if (mListener != null) { mListener.onChanged(this, mTracking, checked, mSlider.getProgress()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index e5e287d..f349036 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -41,7 +41,6 @@ import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -78,6 +77,7 @@ import com.android.systemui.RecentsComponent; import com.android.systemui.SearchPanelView; import com.android.systemui.SystemUI; import com.android.systemui.statusbar.phone.KeyguardTouchDelegate; +import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import java.util.ArrayList; import java.util.Locale; @@ -98,8 +98,6 @@ public abstract class BaseStatusBar extends SystemUI implements protected static final int MSG_HIDE_HEADS_UP = 1027; protected static final int MSG_ESCALATE_HEADS_UP = 1028; - public static final boolean ENABLE_NOTIFICATION_STACK = SystemProperties - .getBoolean("persist.notifications.use_stack", false); protected static final boolean ENABLE_HEADS_UP = true; // scores above this threshold should be displayed in heads up mode. protected static final int INTERRUPTION_THRESHOLD = 10; @@ -120,7 +118,7 @@ public abstract class BaseStatusBar extends SystemUI implements // all notifications protected NotificationData mNotificationData = new NotificationData(); - protected ViewGroup mPile; + protected NotificationStackScrollLayout mStackScroller; protected NotificationData.Entry mInterruptingNotificationEntry; protected long mInterruptingNotificationTime; @@ -1033,7 +1031,7 @@ public abstract class BaseStatusBar extends SystemUI implements } // Construct the expanded view. NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView); - if (!inflateViews(entry, mPile)) { + if (!inflateViews(entry, mStackScroller)) { handleNotificationError(key, notification, "Couldn't expand RemoteViews for: " + notification); return null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 6be6d4d..2d2f2f1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -17,45 +17,51 @@ package com.android.systemui.statusbar.phone; import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; import android.util.AttributeSet; -import android.util.EventLog; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; -import com.android.systemui.EventLogTags; import com.android.systemui.R; import com.android.systemui.statusbar.GestureRecorder; +import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; public class NotificationPanelView extends PanelView { public static final boolean DEBUG_GESTURES = true; - Drawable mHandleBar; - int mHandleBarHeight; - View mHandleView; - int mFingers; PhoneStatusBar mStatusBar; - boolean mOkToFlip; + private NotificationStackScrollLayout mNotificationStackScroller; + private int[] mTempLocation = new int[2]; + private int[] mTempChildLocation = new int[2]; + private View mNotificationParent; + public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); } public void setStatusBar(PhoneStatusBar bar) { + if (mStatusBar != null) { + mStatusBar.setOnFlipRunnable(null); + } mStatusBar = bar; + if (bar != null) { + mStatusBar.setOnFlipRunnable(new Runnable() { + @Override + public void run() { + requestPanelHeightUpdate(); + } + }); + } } @Override protected void onFinishInflate() { super.onFinishInflate(); - Resources resources = getContext().getResources(); - mHandleBar = resources.getDrawable(R.drawable.status_bar_close); - mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height); - mHandleView = findViewById(R.id.handle); + mNotificationStackScroller = (NotificationStackScrollLayout) + findViewById(R.id.notification_stack_scroller); + mNotificationParent = findViewById(R.id.notification_container_parent); } @Override @@ -80,61 +86,86 @@ public class NotificationPanelView extends PanelView { return super.dispatchPopulateAccessibilityEvent(event); } - // We draw the handle ourselves so that it's always glued to the bottom of the window. + /** + * Gets the relative position of a view on the screen in regard to this view. + * + * @param requestedView the view we want to find the relative position for + * @return + */ + private int getRelativeTop(View requestedView) { + getLocationOnScreen(mTempLocation); + requestedView.getLocationOnScreen(mTempChildLocation); + return mTempChildLocation[1] - mTempLocation[1]; + } + @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (changed) { - final int pl = getPaddingLeft(); - final int pr = getPaddingRight(); - mHandleBar.setBounds(pl, 0, getWidth() - pr, (int) mHandleBarHeight); - } + public boolean onTouchEvent(MotionEvent event) { + // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference + // implementation. + return super.onTouchEvent(event); } @Override - public void draw(Canvas canvas) { - super.draw(canvas); - final int off = (int) (getHeight() - mHandleBarHeight - getPaddingBottom()); - canvas.translate(0, off); - mHandleBar.setState(mHandleView.getDrawableState()); - mHandleBar.draw(canvas); - canvas.translate(0, -off); + protected boolean isScrolledToBottom() { + if (!isInSettings()) { + return mNotificationStackScroller.isScrolledToBottom(); + } + return super.isScrolledToBottom(); } @Override - public boolean onTouchEvent(MotionEvent event) { - if (DEBUG_GESTURES) { - if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { - EventLog.writeEvent(EventLogTags.SYSUI_NOTIFICATIONPANEL_TOUCH, - event.getActionMasked(), (int) event.getX(), (int) event.getY()); - } + protected int getMaxPanelHeight() { + if (!isInSettings()) { + int maxPanelHeight = super.getMaxPanelHeight(); + int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin(); + return maxPanelHeight - emptyBottomMargin; } - if (PhoneStatusBar.SETTINGS_DRAG_SHORTCUT && mStatusBar.mHasFlipSettings) { - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - mOkToFlip = getExpandedHeight() == 0; - break; - case MotionEvent.ACTION_POINTER_DOWN: - if (mOkToFlip) { - float miny = event.getY(0); - float maxy = miny; - for (int i=1; i<event.getPointerCount(); i++) { - final float y = event.getY(i); - if (y < miny) miny = y; - if (y > maxy) maxy = y; - } - if (maxy - miny < mHandleBarHeight) { - if (getMeasuredHeight() < mHandleBarHeight) { - mStatusBar.switchToSettings(); - } else { - mStatusBar.flipToSettings(); - } - mOkToFlip = false; - } - } - break; - } + return super.getMaxPanelHeight(); + } + + private boolean isInSettings() { + return mStatusBar != null && mStatusBar.isFlippedToSettings(); + } + + @Override + protected void onHeightUpdated(float expandedHeight) { + updateNotificationStackHeight(expandedHeight); + } + + /** + * Update the height of the {@link #mNotificationStackScroller} to the new expanded height. + * This is much more efficient than doing it over the layout pass. + * + * @param expandedHeight the new expanded height + */ + private void updateNotificationStackHeight(float expandedHeight) { + float childOffset = getRelativeTop(mNotificationStackScroller) + - mNotificationParent.getTranslationY(); + int newStackHeight = (int) (expandedHeight - childOffset); + int itemHeight = mNotificationStackScroller.getItemHeight(); + int bottomStackPeekSize = mNotificationStackScroller.getBottomStackPeekSize(); + int minStackHeight = itemHeight + bottomStackPeekSize; + if (newStackHeight >= minStackHeight) { + mNotificationParent.setTranslationY(0); + mNotificationStackScroller.setCurrentStackHeight(newStackHeight); + } else { + + // We did not reach the position yet where we actually start growing, + // so we translate the stack upwards. + int translationY = (newStackHeight - minStackHeight); + // A slight parallax effect is introduced in order for the stack to catch up with + // the top card. + float partiallyThere = (float) newStackHeight / minStackHeight; + partiallyThere = Math.max(0, partiallyThere); + translationY += (1 - partiallyThere) * bottomStackPeekSize; + mNotificationParent.setTranslationY(translationY); + mNotificationStackScroller.setCurrentStackHeight( + (int) (expandedHeight - (childOffset + translationY))); } - return mHandleView.dispatchTouchEvent(event); + } + + @Override + protected int getDesiredMeasureHeight() { + return mMaxPanelHeight; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 4b2c3e1..3c8af30 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -25,6 +25,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.widget.FrameLayout; import com.android.systemui.R; @@ -69,7 +70,7 @@ public class PanelView extends FrameLayout { private View mHandleView; private float mPeekHeight; - private float mTouchOffset; + private float mInitialOffsetOnTouch; private float mExpandedFraction = 0; private float mExpandedHeight = 0; private boolean mJustPeeked; @@ -77,6 +78,7 @@ public class PanelView extends FrameLayout { private boolean mRubberbanding; private boolean mTracking; private int mTrackingPointer; + private int mTouchSlop; private TimeAnimator mTimeAnimator; private ObjectAnimator mPeekAnimator; @@ -198,7 +200,6 @@ public class PanelView extends FrameLayout { } } - private int[] mAbsPos = new int[2]; PanelBar mBar; private final TimeListener mAnimationCallback = new TimeListener() { @@ -220,7 +221,7 @@ public class PanelView extends FrameLayout { }; private float mVel, mAccel; - private int mFullHeight = 0; + protected int mMaxPanelHeight = 0; private String mViewName; protected float mInitialTouchY; protected float mFinalTouchY; @@ -253,13 +254,13 @@ public class PanelView extends FrameLayout { mTimeAnimator.start(); mRubberbanding = mRubberbandingEnabled // is it enabled at all? - && mExpandedHeight > getFullHeight() // are we past the end? + && mExpandedHeight > getMaxPanelHeight() // are we past the end? && mVel >= -mFlingGestureMinDistPx; // was this not possibly a "close" gesture? if (mRubberbanding) { mClosing = true; } else if (mVel == 0) { // if the panel is less than halfway open, close it - mClosing = (mFinalTouchY / getFullHeight()) < 0.5f; + mClosing = (mFinalTouchY / getMaxPanelHeight()) < 0.5f; } else { mClosing = mExpandedHeight > 0 && mVel < 0; } @@ -268,7 +269,7 @@ public class PanelView extends FrameLayout { if (DEBUG) logf("tick: v=%.2fpx/s dt=%.4fs", mVel, dt); if (DEBUG) logf("tick: before: h=%d", (int) mExpandedHeight); - final float fh = getFullHeight(); + final float fh = getMaxPanelHeight(); boolean braking = false; if (BRAKES) { if (mClosing) { @@ -351,6 +352,9 @@ public class PanelView extends FrameLayout { mPeekHeight = res.getDimension(R.dimen.peek_height) + getPaddingBottom() // our window might have a dropshadow - (mHandleView == null ? 0 : mHandleView.getPaddingTop()); // the handle might have a topshadow + + final ViewConfiguration configuration = ViewConfiguration.get(getContext()); + mTouchSlop = configuration.getScaledTouchSlop(); } private void trackMovement(MotionEvent event) { @@ -363,10 +367,221 @@ public class PanelView extends FrameLayout { event.offsetLocation(-deltaX, -deltaY); } - // Pass all touches along to the handle, allowing the user to drag the panel closed from its interior @Override public boolean onTouchEvent(MotionEvent event) { - return mHandleView.dispatchTouchEvent(event); + + /* + * We capture touch events here and update the expand height here in case according to + * the users fingers. This also handles multi-touch. + * + * If the user just clicks shortly, we give him a quick peek of the shade. + * + * Flinging is also enabled in order to open or close the shade. + */ + + int pointerIndex = event.findPointerIndex(mTrackingPointer); + if (pointerIndex < 0) { + pointerIndex = 0; + mTrackingPointer = event.getPointerId(pointerIndex); + } + final float y = event.getY(pointerIndex); + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mTracking = true; + if (mHandleView != null) { + mHandleView.setPressed(true); + postInvalidate(); // catch the press state change + } + + mInitialTouchY = y; + initVelocityTracker(); + trackMovement(event); + mTimeAnimator.cancel(); // end any outstanding animations + mBar.onTrackingStarted(PanelView.this); + mInitialOffsetOnTouch = mExpandedHeight; + if (mExpandedHeight == 0) { + mJustPeeked = true; + runPeekAnimation(); + } + break; + + case MotionEvent.ACTION_POINTER_UP: + final int upPointer = event.getPointerId(event.getActionIndex()); + if (mTrackingPointer == upPointer) { + // gesture is ongoing, find a new pointer to track + final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1; + final float newY = event.getY(newIndex); + mTrackingPointer = event.getPointerId(newIndex); + mInitialOffsetOnTouch = mExpandedHeight; + mInitialTouchY = newY; + } + break; + + case MotionEvent.ACTION_MOVE: + final float h = y - mInitialTouchY + mInitialOffsetOnTouch; + if (h > mPeekHeight) { + if (mPeekAnimator != null && mPeekAnimator.isStarted()) { + mPeekAnimator.cancel(); + } + mJustPeeked = false; + } + if (!mJustPeeked) { + setExpandedHeightInternal(h); + mBar.panelExpansionChanged(PanelView.this, mExpandedFraction); + } + + trackMovement(event); + break; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mFinalTouchY = y; + mTracking = false; + mTrackingPointer = -1; + if (mHandleView != null) { + mHandleView.setPressed(false); + postInvalidate(); // catch the press state change + } + mBar.onTrackingStopped(PanelView.this); + trackMovement(event); + + float vel = getCurrentVelocity(); + fling(vel, true); + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + break; + } + return true; + } + + private float getCurrentVelocity() { + float vel = 0; + float yVel = 0, xVel = 0; + boolean negative = false; + + // the velocitytracker might be null if we got a bad input stream + if (mVelocityTracker == null) { + return 0; + } + + mVelocityTracker.computeCurrentVelocity(1000); + + yVel = mVelocityTracker.getYVelocity(); + negative = yVel < 0; + + xVel = mVelocityTracker.getXVelocity(); + if (xVel < 0) { + xVel = -xVel; + } + if (xVel > mFlingGestureMaxXVelocityPx) { + xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis + } + + vel = (float) Math.hypot(yVel, xVel); + if (vel > mFlingGestureMaxOutputVelocityPx) { + vel = mFlingGestureMaxOutputVelocityPx; + } + + // if you've barely moved your finger, we treat the velocity as 0 + // preventing spurious flings due to touch screen jitter + final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY); + if (deltaY < mFlingGestureMinDistPx + || vel < mFlingExpandMinVelocityPx + ) { + vel = 0; + } + + if (negative) { + vel = -vel; + } + + if (DEBUG) { + logf("gesture: dy=%f vel=(%f,%f) vlinear=%f", + deltaY, + xVel, yVel, + vel); + } + return vel; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + + /* + * If the user drags anywhere inside the panel we intercept it if he moves his finger + * upwards. This allows closing the shade from anywhere inside the panel. + * + * We only do this if the current content is scrolled to the bottom, + * i.e isScrolledToBottom() is true and therefore there is no conflicting scrolling gesture + * possible. + */ + int pointerIndex = event.findPointerIndex(mTrackingPointer); + if (pointerIndex < 0) { + pointerIndex = 0; + mTrackingPointer = event.getPointerId(pointerIndex); + } + final float y = event.getY(pointerIndex); + boolean scrolledToBottom = isScrolledToBottom(); + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mTracking = true; + if (mHandleView != null) { + mHandleView.setPressed(true); + // catch the press state change + postInvalidate(); + } + mInitialTouchY = y; + initVelocityTracker(); + trackMovement(event); + mTimeAnimator.cancel(); // end any outstanding animations + if (mExpandedHeight == 0 || y > getContentHeight()) { + return true; + } + break; + case MotionEvent.ACTION_POINTER_UP: + final int upPointer = event.getPointerId(event.getActionIndex()); + if (mTrackingPointer == upPointer) { + // gesture is ongoing, find a new pointer to track + final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1; + mTrackingPointer = event.getPointerId(newIndex); + final float newY = event.getY(newIndex); + mInitialTouchY = newY; + } + break; + + case MotionEvent.ACTION_MOVE: + final float h = y - mInitialTouchY; + trackMovement(event); + if (scrolledToBottom) { + if (h < -mTouchSlop) { + mInitialOffsetOnTouch = mExpandedHeight; + mInitialTouchY = y; + return true; + } + } + break; + } + return false; + } + + private void initVelocityTracker() { + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + } + mVelocityTracker = FlingTracker.obtain(); + } + + protected boolean isScrolledToBottom() { + return false; + } + + protected float getContentHeight() { + return mExpandedHeight; } @Override @@ -375,134 +590,6 @@ public class PanelView extends FrameLayout { mHandleView = findViewById(R.id.handle); loadDimens(); - - if (DEBUG) logf("handle view: " + mHandleView); - if (mHandleView != null) { - mHandleView.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - int pointerIndex = event.findPointerIndex(mTrackingPointer); - if (pointerIndex < 0) { - pointerIndex = 0; - mTrackingPointer = event.getPointerId(pointerIndex); - } - final float y = event.getY(pointerIndex); - final float rawDelta = event.getRawY() - event.getY(); - final float rawY = y + rawDelta; - if (DEBUG) logf("handle.onTouch: a=%s p=[%d,%d] y=%.1f rawY=%.1f off=%.1f", - MotionEvent.actionToString(event.getAction()), - mTrackingPointer, pointerIndex, - y, rawY, mTouchOffset); - PanelView.this.getLocationOnScreen(mAbsPos); - - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - mTracking = true; - mHandleView.setPressed(true); - postInvalidate(); // catch the press state change - mInitialTouchY = y; - mVelocityTracker = FlingTracker.obtain(); - trackMovement(event); - mTimeAnimator.cancel(); // end any outstanding animations - mBar.onTrackingStarted(PanelView.this); - mTouchOffset = (rawY - mAbsPos[1]) - mExpandedHeight; - if (mExpandedHeight == 0) { - mJustPeeked = true; - runPeekAnimation(); - } - break; - - case MotionEvent.ACTION_POINTER_UP: - final int upPointer = event.getPointerId(event.getActionIndex()); - if (mTrackingPointer == upPointer) { - // gesture is ongoing, find a new pointer to track - final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1; - final float newY = event.getY(newIndex); - final float newRawY = newY + rawDelta; - mTrackingPointer = event.getPointerId(newIndex); - mTouchOffset = (newRawY - mAbsPos[1]) - mExpandedHeight; - mInitialTouchY = newY; - } - break; - - case MotionEvent.ACTION_MOVE: - final float h = rawY - mAbsPos[1] - mTouchOffset; - if (h > mPeekHeight) { - if (mPeekAnimator != null && mPeekAnimator.isStarted()) { - mPeekAnimator.cancel(); - } - mJustPeeked = false; - } - if (!mJustPeeked) { - PanelView.this.setExpandedHeightInternal(h); - mBar.panelExpansionChanged(PanelView.this, mExpandedFraction); - } - - trackMovement(event); - break; - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - mFinalTouchY = y; - mTracking = false; - mTrackingPointer = -1; - mHandleView.setPressed(false); - postInvalidate(); // catch the press state change - mBar.onTrackingStopped(PanelView.this); - trackMovement(event); - - float vel = 0, yVel = 0, xVel = 0; - boolean negative = false; - - if (mVelocityTracker != null) { - // the velocitytracker might be null if we got a bad input stream - mVelocityTracker.computeCurrentVelocity(1000); - - yVel = mVelocityTracker.getYVelocity(); - negative = yVel < 0; - - xVel = mVelocityTracker.getXVelocity(); - if (xVel < 0) { - xVel = -xVel; - } - if (xVel > mFlingGestureMaxXVelocityPx) { - xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis - } - - vel = (float)Math.hypot(yVel, xVel); - if (vel > mFlingGestureMaxOutputVelocityPx) { - vel = mFlingGestureMaxOutputVelocityPx; - } - - mVelocityTracker.recycle(); - mVelocityTracker = null; - } - - // if you've barely moved your finger, we treat the velocity as 0 - // preventing spurious flings due to touch screen jitter - final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY); - if (deltaY < mFlingGestureMinDistPx - || vel < mFlingExpandMinVelocityPx - ) { - vel = 0; - } - - if (negative) { - vel = -vel; - } - - if (DEBUG) logf("gesture: dy=%f vel=(%f,%f) vlinear=%f", - deltaY, - xVel, yVel, - vel); - - fling(vel, true); - - break; - } - return true; - }}); - } } public void fling(float vel, boolean always) { @@ -543,19 +630,18 @@ public class PanelView extends FrameLayout { // Did one of our children change size? int newHeight = getMeasuredHeight(); - if (newHeight != mFullHeight) { - mFullHeight = newHeight; - // If the user isn't actively poking us, let's rubberband to the content - if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted() - && mExpandedHeight > 0 && mExpandedHeight != mFullHeight) { - mExpandedHeight = mFullHeight; - } + if (newHeight != mMaxPanelHeight) { + mMaxPanelHeight = newHeight; } heightMeasureSpec = MeasureSpec.makeMeasureSpec( - (int) mExpandedHeight, MeasureSpec.AT_MOST); // MeasureSpec.getMode(heightMeasureSpec)); + getDesiredMeasureHeight(), MeasureSpec.AT_MOST); setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); } + protected int getDesiredMeasureHeight() { + return (int) mExpandedHeight; + } + public void setExpandedHeight(float height) { if (DEBUG) logf("setExpandedHeight(%.1f)", height); @@ -569,8 +655,20 @@ public class PanelView extends FrameLayout { @Override protected void onLayout (boolean changed, int left, int top, int right, int bottom) { - if (DEBUG) logf("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom, (int)mExpandedHeight, mFullHeight); + if (DEBUG) logf("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom, + (int)mExpandedHeight, mMaxPanelHeight); super.onLayout(changed, left, top, right, bottom); + requestPanelHeightUpdate(); + } + + protected void requestPanelHeightUpdate() { + float currentMaxPanelHeight = getMaxPanelHeight(); + + // If the user isn't actively poking us, let's update the height + if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted() + && mExpandedHeight > 0 && currentMaxPanelHeight != mExpandedHeight) { + setExpandedHeightInternal(currentMaxPanelHeight); + } } public void setExpandedHeightInternal(float h) { @@ -583,7 +681,7 @@ public class PanelView extends FrameLayout { h = 0; } - float fh = getFullHeight(); + float fh = getMaxPanelHeight(); if (fh == 0) { // Hmm, full height hasn't been computed yet } @@ -593,9 +691,13 @@ public class PanelView extends FrameLayout { mExpandedHeight = h; - if (DEBUG) logf("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh, mTracking?"T":"f", mRubberbanding?"T":"f"); + if (DEBUG) { + logf("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh, + mTracking ? "T" : "f", mRubberbanding ? "T" : "f"); + } + + onHeightUpdated(mExpandedHeight); - requestLayout(); // FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); // lp.height = (int) mExpandedHeight; // setLayoutParams(lp); @@ -603,13 +705,23 @@ public class PanelView extends FrameLayout { mExpandedFraction = Math.min(1f, (fh == 0) ? 0 : h / fh); } - private float getFullHeight() { - if (mFullHeight <= 0) { - if (DEBUG) logf("Forcing measure() since fullHeight=" + mFullHeight); + protected void onHeightUpdated(float expandedHeight) { + requestLayout(); + } + + /** + * This returns the maximum height of the panel. Children should override this if their + * desired height is not the full height. + * + * @return the default implementation simply returns the maximum height. + */ + protected int getMaxPanelHeight() { + if (mMaxPanelHeight <= 0) { + if (DEBUG) logf("Forcing measure() since mMaxPanelHeight=" + mMaxPanelHeight); measure(MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY)); } - return mFullHeight; + return mMaxPanelHeight; } public void setExpandedFraction(float frac) { @@ -621,7 +733,7 @@ public class PanelView extends FrameLayout { } frac = 0; } - setExpandedHeight(getFullHeight() * frac); + setExpandedHeight(getMaxPanelHeight() * frac); } public float getExpandedHeight() { @@ -633,7 +745,7 @@ public class PanelView extends FrameLayout { } public boolean isFullyExpanded() { - return mExpandedHeight >= getFullHeight(); + return mExpandedHeight >= getMaxPanelHeight(); } public boolean isFullyCollapsed() { @@ -681,12 +793,12 @@ public class PanelView extends FrameLayout { } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(String.format("[PanelView(%s): expandedHeight=%f fullHeight=%f closing=%s" + pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%f closing=%s" + " tracking=%s rubberbanding=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s" + "]", this.getClass().getSimpleName(), getExpandedHeight(), - getFullHeight(), + getMaxPanelHeight(), mClosing?"T":"f", mTracking?"T":"f", mRubberbanding?"T":"f", diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 2257aaa..4730f2f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -86,7 +86,6 @@ import com.android.internal.statusbar.StatusBarIcon; import com.android.systemui.DemoMode; import com.android.systemui.EventLogTags; import com.android.systemui.R; -import com.android.systemui.SwipeHelper; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.GestureRecorder; @@ -101,8 +100,6 @@ import com.android.systemui.statusbar.policy.DateView; import com.android.systemui.statusbar.policy.HeadsUpNotificationView; import com.android.systemui.statusbar.policy.LocationController; import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NotificationRowLayout; -import com.android.systemui.statusbar.policy.OnSizeChangedListener; import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; @@ -172,7 +169,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { Display mDisplay; Point mCurrentDisplaySize = new Point(); private float mHeadsUpVerticalOffset; - private int[] mPilePosition = new int[2]; + private int[] mStackScrollerPosition = new int[2]; StatusBarWindowView mStatusBarWindow; PhoneStatusBarView mStatusBarView; @@ -198,7 +195,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { // expanded notifications NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window - View mNotificationScroller; View mExpandedContents; int mNotificationPanelGravity; int mNotificationPanelMarginBottomPx, mNotificationPanelMarginPx; @@ -350,6 +346,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } }}; + private Runnable mOnFlipRunnable; + + public void setOnFlipRunnable(Runnable onFlipRunnable) { + mOnFlipRunnable = onFlipRunnable; + } + @Override public void setZenMode(int mode) { super.setZenMode(mode); @@ -417,7 +419,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder); mStatusBarView.setPanelHolder(holder); - mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(R.id.notification_panel); + mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById( + R.id.notification_panel); mNotificationPanel.setStatusBar(this); mNotificationPanelIsFullScreenWidth = (mNotificationPanel.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT); @@ -443,7 +446,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mHeadsUpNotificationView.setBar(this); } if (MULTIUSER_DEBUG) { - mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(R.id.header_debug_info); + mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById( + R.id.header_debug_info); mNotificationPanelDebugText.setVisibility(View.VISIBLE); } @@ -482,33 +486,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents); mTickerView = mStatusBarView.findViewById(R.id.ticker); - View legacyScrollView = mStatusBarWindow.findViewById(R.id.scroll); - NotificationStackScrollLayout notificationStack - = (NotificationStackScrollLayout) mStatusBarWindow - .findViewById(R.id.notification_stack_scroller); - if (ENABLE_NOTIFICATION_STACK) { - notificationStack.setLongPressListener(getNotificationLongClicker()); - mPile = notificationStack; - legacyScrollView.setVisibility(View.GONE); - - // The scrollview and the notification container are unified now! - // TODO: remove mNotificationScroller entirely once we fully switch to the new Layout - mNotificationScroller = notificationStack; - } else { - mNotificationScroller = legacyScrollView; - // less drawing during pulldowns - mNotificationScroller.setVerticalScrollBarEnabled(false); - NotificationRowLayout rowLayout - = (NotificationRowLayout) mStatusBarWindow.findViewById(R.id.latestItems); - rowLayout.setLayoutTransitionsEnabled(false); - rowLayout.setLongPressListener(getNotificationLongClicker()); - mPile = rowLayout; - notificationStack.setVisibility(View.GONE); - } - - mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout); - + mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById( + R.id.notification_stack_scroller); + mStackScroller.setLongPressListener(getNotificationLongClicker()); + mExpandedContents = mStackScroller; mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header); @@ -551,7 +533,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } } if (mHasFlipSettings) { - mNotificationButton = (ImageView) mStatusBarWindow.findViewById(R.id.notification_button); + mNotificationButton = (ImageView) mStatusBarWindow.findViewById( + R.id.notification_button); if (mNotificationButton != null) { mNotificationButton.setOnClickListener(mNotificationButtonListener); } @@ -593,17 +576,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (isAPhone) { mEmergencyCallLabel = (TextView) mStatusBarWindow.findViewById(R.id.emergency_calls_only); - if (mEmergencyCallLabel != null) { - mNetworkController.addEmergencyLabelView(mEmergencyCallLabel); - mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { }}); - mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - updateCarrierLabelVisibility(false); - }}); - } + // TODO: Uncomment when correctly positioned +// if (mEmergencyCallLabel != null) { +// mNetworkController.addEmergencyLabelView(mEmergencyCallLabel); +// mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() { +// public void onClick(View v) { }}); +// mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { +// @Override +// public void onLayoutChange(View v, int left, int top, int right, int bottom, +// int oldLeft, int oldTop, int oldRight, int oldBottom) { +// updateCarrierLabelVisibility(false); +// }}); +// } } mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label); @@ -621,13 +605,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } // set up the dynamic hide/show of the label - if (!ENABLE_NOTIFICATION_STACK) - ((NotificationRowLayout) mPile).setOnSizeChangedListener(new OnSizeChangedListener() { - @Override - public void onSizeChanged(View view, int w, int h, int oldw, int oldh) { - updateCarrierLabelVisibility(false); - } - }); + // TODO: uncomment, handle this for the Stack scroller aswell +// ((NotificationRowLayout) mStackScroller) +// .setOnSizeChangedListener(new OnSizeChangedListener() { +// @Override +// public void onSizeChanged(View view, int w, int h, int oldw, int oldh) { +// updateCarrierLabelVisibility(false); } // Quick Settings (where available, some restrictions apply) @@ -1066,7 +1049,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } private void loadNotificationShade() { - if (mPile == null) return; + if (mStackScroller == null) return; int N = mNotificationData.size(); @@ -1092,21 +1075,21 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } ArrayList<View> toRemove = new ArrayList<View>(); - for (int i=0; i<mPile.getChildCount(); i++) { - View child = mPile.getChildAt(i); + for (int i=0; i< mStackScroller.getChildCount(); i++) { + View child = mStackScroller.getChildAt(i); if (!toShow.contains(child)) { toRemove.add(child); } } for (View remove : toRemove) { - mPile.removeView(remove); + mStackScroller.removeView(remove); } for (int i=0; i<toShow.size(); i++) { View v = toShow.get(i); if (v.getParent() == null) { - mPile.addView(v, i); + mStackScroller.addView(v, i); } } @@ -1178,15 +1161,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { // The idea here is to only show the carrier label when there is enough room to see it, // i.e. when there aren't enough notifications to fill the panel. if (SPEW) { - Log.d(TAG, String.format("pileh=%d scrollh=%d carrierh=%d", - mPile.getHeight(), mNotificationScroller.getHeight(), mCarrierLabelHeight)); + Log.d(TAG, String.format("stackScrollerh=%d scrollh=%d carrierh=%d", + mStackScroller.getHeight(), mStackScroller.getHeight(), + mCarrierLabelHeight)); } final boolean emergencyCallsShownElsewhere = mEmergencyCallLabel != null; final boolean makeVisible = !(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly()) - && mPile.getHeight() < (mNotificationPanel.getHeight() - mCarrierLabelHeight - mNotificationHeaderHeight) - && mNotificationScroller.getVisibility() == View.VISIBLE; + && mStackScroller.getHeight() < (mNotificationPanel.getHeight() + - mCarrierLabelHeight - mNotificationHeaderHeight) + && mStackScroller.getVisibility() == View.VISIBLE; if (force || mCarrierLabelVisible != makeVisible) { mCarrierLabelVisible = makeVisible; @@ -1229,7 +1214,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (mHasFlipSettings && mFlipSettingsView != null && mFlipSettingsView.getVisibility() == View.VISIBLE - && mNotificationScroller.getVisibility() != View.VISIBLE) { + && mStackScroller.getVisibility() != View.VISIBLE) { // the flip settings panel is unequivocally showing; we should not be shown mClearButton.setVisibility(View.INVISIBLE); } else if (mClearButton.isShown()) { @@ -1483,9 +1468,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } mExpandedVisible = true; - if (!ENABLE_NOTIFICATION_STACK) { - ((NotificationRowLayout) mPile).setLayoutTransitionsEnabled(true); - } if (mNavigationBarView != null) mNavigationBarView.setSlippery(true); @@ -1600,7 +1582,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } mNotificationPanel.expand(); - if (mHasFlipSettings && mNotificationScroller.getVisibility() != View.VISIBLE) { + if (mHasFlipSettings && mStackScroller.getVisibility() != View.VISIBLE) { flipToNotifications(); } @@ -1614,11 +1596,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel(); if (mClearButtonAnim != null) mClearButtonAnim.cancel(); - mNotificationScroller.setVisibility(View.VISIBLE); + mStackScroller.setVisibility(View.VISIBLE); mScrollViewAnim = start( startDelay(FLIP_DURATION_OUT, interpolator(mDecelerateInterpolator, - ObjectAnimator.ofFloat(mNotificationScroller, View.SCALE_X, 0f, 1f) + ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 0f, 1f) .setDuration(FLIP_DURATION_IN) ))); mFlipSettingsViewAnim = start( @@ -1645,6 +1627,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { updateCarrierLabelVisibility(false); } }, FLIP_DURATION - 150); + if (mOnFlipRunnable != null) { + mOnFlipRunnable.run(); + } } @Override @@ -1676,11 +1661,21 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mFlipSettingsView.setScaleX(1f); mFlipSettingsView.setVisibility(View.VISIBLE); mSettingsButton.setVisibility(View.GONE); - mNotificationScroller.setVisibility(View.GONE); - mNotificationScroller.setScaleX(0f); + mStackScroller.setVisibility(View.GONE); + mStackScroller.setScaleX(0f); mNotificationButton.setVisibility(View.VISIBLE); mNotificationButton.setAlpha(1f); mClearButton.setVisibility(View.GONE); + if (mOnFlipRunnable != null) { + mOnFlipRunnable.run(); + } + } + + public boolean isFlippedToSettings() { + if (mFlipSettingsView != null) { + return mFlipSettingsView.getVisibility() == View.VISIBLE; + } + return false; } public void flipToSettings() { @@ -1704,15 +1699,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mScrollViewAnim = start( setVisibilityWhenDone( interpolator(mAccelerateInterpolator, - ObjectAnimator.ofFloat(mNotificationScroller, View.SCALE_X, 1f, 0f) + ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 1f, 0f) ) .setDuration(FLIP_DURATION_OUT), - mNotificationScroller, View.INVISIBLE)); + mStackScroller, View.INVISIBLE)); mSettingsButtonAnim = start( setVisibilityWhenDone( ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f) .setDuration(FLIP_DURATION), - mNotificationScroller, View.INVISIBLE)); + mStackScroller, View.INVISIBLE)); mNotificationButton.setVisibility(View.VISIBLE); mNotificationButtonAnim = start( ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f) @@ -1727,6 +1722,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { updateCarrierLabelVisibility(false); } }, FLIP_DURATION - 150); + if (mOnFlipRunnable != null) { + mOnFlipRunnable.run(); + } } public void flipPanels() { @@ -1766,8 +1764,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel(); if (mClearButtonAnim != null) mClearButtonAnim.cancel(); - mNotificationScroller.setScaleX(1f); - mNotificationScroller.setVisibility(View.VISIBLE); + mStackScroller.setScaleX(1f); + mStackScroller.setVisibility(View.VISIBLE); mSettingsButton.setAlpha(1f); mSettingsButton.setVisibility(View.VISIBLE); mNotificationPanel.setVisibility(View.GONE); @@ -1777,9 +1775,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } mExpandedVisible = false; - if (!ENABLE_NOTIFICATION_STACK) { - ((NotificationRowLayout) mPile).setLayoutTransitionsEnabled(false); - } if (mNavigationBarView != null) mNavigationBarView.setSlippery(false); visibilityChanged(false); @@ -1806,53 +1801,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); } - /** - * Enables or disables layers on the children of the notifications pile. - * - * When layers are enabled, this method attempts to enable layers for the minimal - * number of children. Only children visible when the notification area is fully - * expanded will receive a layer. The technique used in this method might cause - * more children than necessary to get a layer (at most one extra child with the - * current UI.) - * - * @param layerType {@link View#LAYER_TYPE_NONE} or {@link View#LAYER_TYPE_HARDWARE} - */ - private void setPileLayers(int layerType) { - final int count = mPile.getChildCount(); - - switch (layerType) { - case View.LAYER_TYPE_NONE: - for (int i = 0; i < count; i++) { - mPile.getChildAt(i).setLayerType(layerType, null); - } - break; - case View.LAYER_TYPE_HARDWARE: - final int[] location = new int[2]; - mNotificationPanel.getLocationInWindow(location); - - final int left = location[0]; - final int top = location[1]; - final int right = left + mNotificationPanel.getWidth(); - final int bottom = top + getExpandedViewMaxHeight(); - - final Rect childBounds = new Rect(); - - for (int i = 0; i < count; i++) { - final View view = mPile.getChildAt(i); - view.getLocationInWindow(location); - - childBounds.set(location[0], location[1], - location[0] + view.getWidth(), location[1] + view.getHeight()); - - if (childBounds.intersects(left, top, right, bottom)) { - view.setLayerType(layerType, null); - } - } - - break; - } - } - public boolean interceptTouchEvent(MotionEvent event) { if (DEBUG_GESTURES) { if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { @@ -2230,11 +2178,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { pw.println(" mTicking=" + mTicking); pw.println(" mTracking=" + mTracking); pw.println(" mDisplayMetrics=" + mDisplayMetrics); - pw.println(" mPile: " + viewInfo(mPile)); + pw.println(" mStackScroller: " + viewInfo(mStackScroller)); pw.println(" mTickerView: " + viewInfo(mTickerView)); - pw.println(" mNotificationScroller: " + viewInfo(mNotificationScroller) - + " scroll " + mNotificationScroller.getScrollX() - + "," + mNotificationScroller.getScrollY()); + pw.println(" mStackScroller: " + viewInfo(mStackScroller) + + " scroll " + mStackScroller.getScrollX() + + "," + mStackScroller.getScrollY()); } pw.print(" mInteractingWindows="); pw.println(mInteractingWindows); @@ -2409,8 +2357,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (ENABLE_HEADS_UP && mHeadsUpNotificationView != null) { mHeadsUpNotificationView.setMargin(mNotificationPanelMarginPx); - mPile.getLocationOnScreen(mPilePosition); - mHeadsUpVerticalOffset = mPilePosition[1] - mNaturalBarHeight; + mStackScroller.getLocationOnScreen(mStackScrollerPosition); + mHeadsUpVerticalOffset = mStackScrollerPosition[1] - mNaturalBarHeight; } updateCarrierLabelVisibility(false); @@ -2428,7 +2376,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { private View.OnClickListener mClearButtonListener = new View.OnClickListener() { public void onClick(View v) { - // TODO: Handle this better with notification stack scroller synchronized (mNotificationData) { mPostCollapseCleanup = new Runnable() { @Override @@ -2437,86 +2384,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { Log.v(TAG, "running post-collapse cleanup"); } try { - if (!ENABLE_NOTIFICATION_STACK) { - ((NotificationRowLayout) mPile).setViewRemoval(true); - } mBarService.onClearAllNotifications(mCurrentUserId); } catch (Exception ex) { } } }; - if(ENABLE_NOTIFICATION_STACK) { - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); - return; - } - - // animate-swipe all dismissable notifications, then animate the shade closed - int numChildren = mPile.getChildCount(); - - int scrollTop = mNotificationScroller.getScrollY(); - int scrollBottom = scrollTop + mNotificationScroller.getHeight(); - final ArrayList<View> snapshot = new ArrayList<View>(numChildren); - for (int i=0; i<numChildren; i++) { - final View child = mPile.getChildAt(i); - if (((SwipeHelper.Callback) mPile).canChildBeDismissed(child) - && child.getBottom() > scrollTop && child.getTop() < scrollBottom) { - snapshot.add(child); - } - } - if (snapshot.isEmpty()) { - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); - return; - } - new Thread(new Runnable() { - @Override - public void run() { - // Decrease the delay for every row we animate to give the sense of - // accelerating the swipes - final int ROW_DELAY_DECREMENT = 10; - int currentDelay = 140; - int totalDelay = 0; - - - if (!ENABLE_NOTIFICATION_STACK) { - // Set the shade-animating state to avoid doing other work during - // all of these animations. In particular, avoid layout and - // redrawing when collapsing the shade. - ((NotificationRowLayout) mPile).setViewRemoval(false); - } - - View sampleView = snapshot.get(0); - int width = sampleView.getWidth(); - final int dir = sampleView.isLayoutRtl() ? -1 : +1; - final int velocity = dir * width * 8; // 1000/8 = 125 ms duration - for (final View _v : snapshot) { - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - if (!ENABLE_NOTIFICATION_STACK) { - ((NotificationRowLayout) mPile).dismissRowAnimated( - _v, velocity); - } else { - ((NotificationStackScrollLayout) mPile).dismissRowAnimated( - _v, velocity); - } - } - }, totalDelay); - currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT); - totalDelay += currentDelay; - } - // Delay the collapse animation until after all swipe animations have - // finished. Provide some buffer because there may be some extra delay - // before actually starting each swipe animation. Ideally, we'd - // synchronize the end of those animations with the start of the collaps - // exactly. - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); - } - }, totalDelay + 225); - } - }).start(); + animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); + return; + // TODO: Handle this better with notification stack scroller } } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index eeae081..a7121c4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -24,13 +24,13 @@ import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.view.ViewRootImpl; import android.widget.FrameLayout; import com.android.systemui.ExpandHelper; import com.android.systemui.R; import com.android.systemui.statusbar.BaseStatusBar; +import com.android.systemui.statusbar.policy.ScrollAdapter; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; @@ -40,9 +40,8 @@ public class StatusBarWindowView extends FrameLayout public static final boolean DEBUG = BaseStatusBar.DEBUG; private ExpandHelper mExpandHelper; - private ViewGroup latestItems; + private NotificationStackScrollLayout mStackScrollLayout; private NotificationPanelView mNotificationPanel; - private View mNotificationScroller; PhoneStatusBar mService; @@ -56,37 +55,15 @@ public class StatusBarWindowView extends FrameLayout protected void onAttachedToWindow () { super.onAttachedToWindow(); - ExpandHelper.ScrollAdapter scrollAdapter; - if (BaseStatusBar.ENABLE_NOTIFICATION_STACK) { - NotificationStackScrollLayout stackScrollLayout = - (NotificationStackScrollLayout) findViewById(R.id.notification_stack_scroller); - - // ScrollView and notification container are unified in a single view now. - latestItems = stackScrollLayout; - scrollAdapter = stackScrollLayout; - mNotificationScroller = stackScrollLayout; - } else { - latestItems = (ViewGroup) findViewById(R.id.latestItems); - mNotificationScroller = findViewById(R.id.scroll); - scrollAdapter = new ExpandHelper.ScrollAdapter() { - @Override - public boolean isScrolledToTop() { - return mNotificationScroller.getScrollY() == 0; - } - - @Override - public View getHostView() { - return mNotificationScroller; - } - }; - } + mStackScrollLayout = (NotificationStackScrollLayout) findViewById( + R.id.notification_stack_scroller); mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel); int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height); int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height); - mExpandHelper = new ExpandHelper(getContext(), (ExpandHelper.Callback) latestItems, + mExpandHelper = new ExpandHelper(getContext(), mStackScrollLayout, minHeight, maxHeight); mExpandHelper.setEventSource(this); - mExpandHelper.setScrollAdapter(scrollAdapter); + mExpandHelper.setScrollAdapter(mStackScrollLayout); // We really need to be able to animate while window animations are going on // so that activities may be started asynchronously from panel animations @@ -113,7 +90,7 @@ public class StatusBarWindowView extends FrameLayout public boolean onInterceptTouchEvent(MotionEvent ev) { boolean intercept = false; if (mNotificationPanel.isFullyExpanded() - && mNotificationScroller.getVisibility() == View.VISIBLE) { + && mStackScrollLayout.getVisibility() == View.VISIBLE) { intercept = mExpandHelper.onInterceptTouchEvent(ev); } if (!intercept) { @@ -122,7 +99,7 @@ public class StatusBarWindowView extends FrameLayout if (intercept) { MotionEvent cancellation = MotionEvent.obtain(ev); cancellation.setAction(MotionEvent.ACTION_CANCEL); - latestItems.onInterceptTouchEvent(cancellation); + mStackScrollLayout.onInterceptTouchEvent(cancellation); cancellation.recycle(); } return intercept; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ScrollAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ScrollAdapter.java new file mode 100644 index 0000000..f35e22d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ScrollAdapter.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.statusbar.policy; + +import android.view.View; + +/** + * A scroll adapter which can be queried for meta information about the scroll state + */ +public interface ScrollAdapter { + + /** + * @return Whether the view returned by {@link #getHostView()} is scrolled to the top + */ + public boolean isScrolledToTop(); + + /** + * @return Whether the view returned by {@link #getHostView()} is scrolled to the bottom + */ + public boolean isScrolledToBottom(); + + /** + * @return The view in which the scrolling is performed + */ + public View getHostView(); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index f6eeb6d..04b7f53 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -39,12 +39,13 @@ import com.android.systemui.R; import com.android.systemui.SwipeHelper; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.stack.StackScrollState.ViewState; +import com.android.systemui.statusbar.policy.ScrollAdapter; /** * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack. */ public class NotificationStackScrollLayout extends ViewGroup - implements SwipeHelper.Callback, ExpandHelper.Callback, ExpandHelper.ScrollAdapter { + implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter { private static final String TAG = "NotificationStackScrollLayout"; private static final boolean DEBUG = false; @@ -55,7 +56,7 @@ public class NotificationStackScrollLayout extends ViewGroup private static final int INVALID_POINTER = -1; private SwipeHelper mSwipeHelper; - private boolean mAllowScrolling = true; + private boolean mSwipingInProgress = true; private int mCurrentStackHeight = Integer.MAX_VALUE; private int mOwnScrollY; private int mMaxLayoutHeight; @@ -89,7 +90,7 @@ public class NotificationStackScrollLayout extends ViewGroup * The current State this Layout is in */ private final StackScrollState mCurrentStackScrollState = new StackScrollState(this); - + private OnChildLocationsChangedListener mListener; public NotificationStackScrollLayout(Context context) { @@ -279,7 +280,7 @@ public class NotificationStackScrollLayout extends ViewGroup } /** - * Get the current height of the view. This is at most the size of the view given by a the + * Get the current height of the view. This is at most the msize of the view given by a the * layout but it can also be made smaller by setting {@link #mCurrentStackHeight} * * @return either the layout height or the externally defined height, whichever is smaller @@ -288,6 +289,14 @@ public class NotificationStackScrollLayout extends ViewGroup return Math.min(mMaxLayoutHeight, mCurrentStackHeight); } + public int getItemHeight() { + return mCollapsedSize; + } + + public int getBottomStackPeekSize() { + return mBottomStackPeekSize; + } + public void setLongPressListener(View.OnLongClickListener listener) { mSwipeHelper.setLongPressListener(listener); } @@ -298,15 +307,15 @@ public class NotificationStackScrollLayout extends ViewGroup if (veto != null && veto.getVisibility() != View.GONE) { veto.performClick(); } - allowScrolling(true); + setSwipingInProgress(false); } public void onBeginDrag(View v) { - allowScrolling(false); + setSwipingInProgress(true); } public void onDragCancelled(View v) { - allowScrolling(true); + setSwipingInProgress(false); } public View getChildAtPosition(MotionEvent ev) { @@ -365,8 +374,11 @@ public class NotificationStackScrollLayout extends ViewGroup return (veto != null && veto.getVisibility() != View.GONE); } - private void allowScrolling(boolean allow) { - mAllowScrolling = allow; + private void setSwipingInProgress(boolean isSwiped) { + mSwipingInProgress = isSwiped; + if(isSwiped) { + requestDisallowInterceptTouchEvent(true); + } } @Override @@ -386,7 +398,7 @@ public class NotificationStackScrollLayout extends ViewGroup @Override public boolean onTouchEvent(MotionEvent ev) { boolean scrollerWantsIt = false; - if (mAllowScrolling) { + if (!mSwipingInProgress) { scrollerWantsIt = onScrollTouch(ev); } boolean horizontalSwipeWantsIt = false; @@ -409,12 +421,6 @@ public class NotificationStackScrollLayout extends ViewGroup } boolean isBeingDragged = !mScroller.isFinished(); setIsBeingDragged(isBeingDragged); - if (isBeingDragged) { - final ViewParent parent = getParent(); - if (parent != null) { - parent.requestDisallowInterceptTouchEvent(true); - } - } /* * If being flinged and user touches, stop the fling. isFinished @@ -439,10 +445,6 @@ public class NotificationStackScrollLayout extends ViewGroup final int y = (int) ev.getY(activePointerIndex); int deltaY = mLastMotionY - y; if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) { - final ViewParent parent = getParent(); - if (parent != null) { - parent.requestDisallowInterceptTouchEvent(true); - } setIsBeingDragged(true); if (deltaY > 0) { deltaY -= mTouchSlop; @@ -642,7 +644,7 @@ public class NotificationStackScrollLayout extends ViewGroup if (getChildCount() > 0) { int contentHeight = getContentHeight(); scrollRange = Math.max(0, - contentHeight - mMaxLayoutHeight + mCollapsedSize); + contentHeight - mMaxLayoutHeight + mBottomStackPeekSize); } return scrollRange; } @@ -697,7 +699,7 @@ public class NotificationStackScrollLayout extends ViewGroup @Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean scrollWantsIt = false; - if (mAllowScrolling) { + if (!mSwipingInProgress) { scrollWantsIt = onInterceptTouchEventScroll(ev); } boolean swipeWantsIt = false; @@ -763,10 +765,6 @@ public class NotificationStackScrollLayout extends ViewGroup mLastMotionY = y; initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); - final ViewParent parent = getParent(); - if (parent != null) { - parent.requestDisallowInterceptTouchEvent(true); - } } break; } @@ -823,6 +821,7 @@ public class NotificationStackScrollLayout extends ViewGroup private void setIsBeingDragged(boolean isDragged) { mIsBeingDragged = isDragged; if (isDragged) { + requestDisallowInterceptTouchEvent(true); mSwipeHelper.removeLongPressCallback(); } } @@ -841,10 +840,19 @@ public class NotificationStackScrollLayout extends ViewGroup } @Override + public boolean isScrolledToBottom() { + return mOwnScrollY >= getScrollRange(); + } + + @Override public View getHostView() { return this; } + public int getEmptyBottomMargin() { + return Math.max(getHeight() - mContentHeight, 0); + } + /** * A listener that is notified when some child locations might have changed. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java index 6d2ba6a..4745f3b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java @@ -86,7 +86,7 @@ public class StackScrollAlgorithm { // First we reset the view states to their default values. resultState.resetViewStates(); - // The first element is always in there so it's initialized with 1.0f. + // The first element is always in there so it's initialized with 1.0f; algorithmState.itemsInTopStack = 1.0f; algorithmState.partialInTop = 0.0f; algorithmState.lastTopStackIndex = 0; @@ -102,7 +102,7 @@ public class StackScrollAlgorithm { // Phase 3: updateZValuesForState(resultState, algorithmState); - // Write the algorithm state to the result. + // write the algorithm state to the result resultState.setScrollY(algorithmState.scrollY); } @@ -151,7 +151,7 @@ public class StackScrollAlgorithm { // Case 2: // First element of regular scrollview comes next, so the position is just the // scrolling position - nextYPosition = scrollOffset; + nextYPosition = Math.min(scrollOffset, transitioningPositionStart); childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING; } else if (nextYPosition >= transitioningPositionStart) { if (currentYPosition >= transitioningPositionStart) { @@ -180,6 +180,7 @@ public class StackScrollAlgorithm { if (childViewState.location == StackScrollState.ViewState.LOCATION_UNKNOWN) { Log.wtf(LOG_TAG, "Failed to assign location for child " + i); } + nextYPosition = Math.max(0, nextYPosition); currentYPosition = nextYPosition; yPositionInScrollView = yPositionInScrollViewAfterElement; } @@ -253,6 +254,8 @@ public class StackScrollAlgorithm { nextYPosition = mCollapsedSize + mPaddingBetweenElements - mTopStackIndentationFunctor.getValue( algorithmState.itemsInTopStack - i - 1); + nextYPosition = Math.min(nextYPosition, mLayoutHeight - mCollapsedSize + - mBottomStackPeekSize); if (paddedIndex == 0) { childViewState.alpha = 1.0f - algorithmState.partialInTop; childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN; diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml index ef640d5..03d920a 100644 --- a/packages/VpnDialogs/AndroidManifest.xml +++ b/packages/VpnDialogs/AndroidManifest.xml @@ -1,10 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.vpndialogs"> <application android:label="VpnDialogs" android:allowBackup="false" > <activity android:name=".ConfirmDialog" - android:theme="@*android:style/Theme.Holo.Dialog.Alert"> + android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.DEFAULT"/> @@ -12,7 +30,7 @@ </activity> <activity android:name=".ManageDialog" - android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" android:noHistory="true"> <intent-filter> <action android:name="android.intent.action.MAIN"/> diff --git a/packages/WallpaperCropper/AndroidManifest.xml b/packages/WallpaperCropper/AndroidManifest.xml index 27755bd..81d1085 100644 --- a/packages/WallpaperCropper/AndroidManifest.xml +++ b/packages/WallpaperCropper/AndroidManifest.xml @@ -1,3 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.wallpapercropper" > <uses-permission android:name="android.permission.SET_WALLPAPER" /> diff --git a/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml b/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml index 97d7001..cf78989 100644 --- a/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml +++ b/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml @@ -28,7 +28,7 @@ android:layout_height="match_parent" /> <ProgressBar android:id="@+id/loading" - style="@android:style/Widget.Holo.ProgressBar.Large" + style="@android:style/Widget.DeviceDefault.Light.ProgressBar.Large" android:visibility="invisible" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/packages/WallpaperCropper/res/values/styles.xml b/packages/WallpaperCropper/res/values/styles.xml index 2b63fe0..b27a387 100644 --- a/packages/WallpaperCropper/res/values/styles.xml +++ b/packages/WallpaperCropper/res/values/styles.xml @@ -15,13 +15,13 @@ --> <resources> - <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo"> + <style name="Theme.WallpaperCropper" parent="@android:style/Theme.DeviceDefault.Light"> <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item> <item name="android:windowFullscreen">true</item> <item name="android:windowActionBarOverlay">true</item> </style> - <style name="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar"> + <style name="WallpaperCropperActionBar" parent="android:style/Widget.DeviceDefault.Light.ActionBar"> <item name="android:displayOptions">showCustom</item> <item name="android:background">#88000000</item> </style> diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index afb389e..e9be1d7 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6899,18 +6899,27 @@ public final class ActivityManagerService extends ActivityManagerNative rti.stackId = tr.stack.mStackId; rti.userId = tr.userId; + // Traverse upwards looking for any break between main task activities and + // utility activities. final ArrayList<ActivityRecord> activities = tr.mActivities; - int numSet = 0; - for (int activityNdx = activities.size() - 1; activityNdx >= 0 && numSet < 2; - --activityNdx) { + int activityNdx; + final int numActivities = activities.size(); + for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities; + ++activityNdx) { final ActivityRecord r = activities.get(activityNdx); - if (rti.activityLabel == null && r.recentsLabel != null) { - rti.activityLabel = r.recentsLabel; - ++numSet; + if (r.intent != null && + (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) + != 0) { + break; } - if (rti.activityIcon == null && r.recentsIcon != null) { - rti.activityIcon = r.recentsIcon; - ++numSet; + } + // Traverse downwards starting below break looking for set label and icon. + for (--activityNdx; activityNdx >= 0; --activityNdx) { + final ActivityRecord r = activities.get(activityNdx); + if (r.activityLabel != null || r.activityIcon != null) { + rti.activityLabel = r.activityLabel; + rti.activityIcon = r.activityIcon; + break; } } @@ -6979,21 +6988,13 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void setRecentsLabel(IBinder token, CharSequence recentsLabel) { - synchronized (this) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r != null) { - r.recentsLabel = recentsLabel.toString(); - } - } - } - - @Override - public void setRecentsIcon(IBinder token, Bitmap recentsIcon) { + public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel, + Bitmap activityIcon) { synchronized (this) { ActivityRecord r = ActivityRecord.isInStackLocked(token); if (r != null) { - r.recentsIcon = recentsIcon; + r.activityLabel = activityLabel.toString(); + r.activityIcon = activityIcon; } } } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 77f5c59..33b12c5 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -148,8 +148,8 @@ final class ActivityRecord { boolean mStartingWindowShown = false; ActivityContainer mInitialActivityContainer; - String recentsLabel; - Bitmap recentsIcon; + String activityLabel; + Bitmap activityIcon; void dump(PrintWriter pw, String prefix) { final long now = SystemClock.uptimeMillis(); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java index 9916435..64b51c9 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java @@ -27,8 +27,12 @@ import java.util.ArrayList; import java.util.List; /** - * CecDevice class represents a CEC logical device characterized - * by its device type. A physical device can contain the functions of + * HdmiCecDevice class represents a CEC logical device characterized + * by its device type. It is a superclass of those serving concrete device type. + * Currently we're interested in playback(one of sources), display(sink) device type + * only. The support for the other types like recorder, audio system will come later. + * + * <p>A physical device can contain the functions of * more than one logical device, in which case it should create * as many logical devices as necessary. * @@ -41,7 +45,7 @@ import java.util.List; * * <p>Declared as package-private, accessed by HdmiCecService only. */ -final class HdmiCecDevice { +abstract class HdmiCecDevice { private static final String TAG = "HdmiCecDevice"; private final int mType; @@ -49,48 +53,56 @@ final class HdmiCecDevice { // List of listeners to the message/event coming to the device. private final List<IHdmiCecListener> mListeners = new ArrayList<IHdmiCecListener>(); private final Binder mBinder = new Binder(); + private final HdmiCecService mService; - private String mName; private boolean mIsActiveSource; /** + * Factory method that creates HdmiCecDevice instance to the device type. + */ + public static HdmiCecDevice create(HdmiCecService service, int type) { + if (type == HdmiCec.DEVICE_PLAYBACK) { + return new HdmiCecDevicePlayback(service, type); + } else if (type == HdmiCec.DEVICE_TV) { + return new HdmiCecDeviceTv(service, type); + } + return null; + } + + /** * Constructor. */ - public HdmiCecDevice(int type) { + public HdmiCecDevice(HdmiCecService service, int type) { + mService = service; mType = type; mIsActiveSource = false; } /** - * Return the binder token that identifies this instance. + * Called right after the class is instantiated. This method can be used to + * implement any initialization tasks for the instance. */ - public Binder getToken() { - return mBinder; - } + abstract public void initialize(); /** - * Return the type of this device. + * Return the binder token that identifies this instance. */ - public int getType() { - return mType; + public Binder getToken() { + return mBinder; } /** - * Set the name of the device. The name will be transferred via the message - * <Set OSD Name> to other HDMI-CEC devices connected through HDMI - * cables and shown on TV screen to identify the devicie. - * - * @param name name of the device + * Return the service instance. */ - public void setName(String name) { - mName = name; + public HdmiCecService getService() { + return mService; } /** - * Return the name of this device. + * Return the type of this device. */ - public String getName() { - return mName; + public int getType() { + return mType; } /** @@ -128,6 +140,7 @@ final class HdmiCecDevice { if (opcode == HdmiCec.MESSAGE_ACTIVE_SOURCE) { mIsActiveSource = false; } + if (mListeners.size() == 0) { return; } @@ -167,4 +180,13 @@ final class HdmiCecDevice { public void setIsActiveSource(boolean state) { mIsActiveSource = state; } + + /** + * Check if the connected sink device is in powered-on state. The default implementation + * simply returns false. Should be overriden by subclass to report the correct state. + */ + public boolean isSinkDeviceOn() { + Log.w(TAG, "Not valid for the device type: " + mType); + return false; + } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java new file mode 100644 index 0000000..0310264 --- /dev/null +++ b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.hdmi; + +import android.hardware.hdmi.HdmiCec; + +/** + * Class for the logical device of playback type. Devices such as DVD/Blueray player + * that support 'playback' feature are classified as playback device. It is common + * that they don't have built-in display, therefore need to talk, stream their contents + * to TV/display device which is connected through HDMI cable. + * + * <p>It closely monitors the status of display device (other devices can be of interest + * too, but with much less priority), declares itself as 'active source' to have + * display show its output, switch the source state as ordered by display that may be + * talking to many other devices connected to it. It also receives commands from display + * such as remote control signal, standby, status report, playback mode. + * + * <p>Declared as package-private, accessed by HdmiCecService only. + */ +final class HdmiCecDevicePlayback extends HdmiCecDevice { + private static final String TAG = "HdmiCecDevicePlayback"; + + private int mSinkDevicePowerStatus; + + /** + * Constructor. + */ + public HdmiCecDevicePlayback(HdmiCecService service, int type) { + super(service, type); + mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_UNKNOWN; + } + + @Override + public void initialize() { + // Playback device tries to obtain the power status of TV/display when created, + // and maintains it all through its lifecycle. CEC spec says there is + // a maximum 1 second response time. Therefore it should be kept in mind + // that there can be as much amount of period of time the power status + // of the display remains unknown after the query is sent out. + queryTvPowerStatus(); + } + + private void queryTvPowerStatus() { + getService().sendMessage(getType(), HdmiCec.ADDR_TV, + HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, HdmiCecService.EMPTY_PARAM); + } + + @Override + public void handleMessage(int srcAddress, int dstAddress, int opcode, byte[] params) { + // Updates power status of display. The cases are: + // 1) Response for the queried power status request arrives. Update the status. + // 2) Broadcast or direct <Standby> command from TV, which is sent as TV itself is going + // into standby mode too. + // 3) Broadcast <Report Physical Address> command from TV, which is sent while it boots up. + if (opcode == HdmiCec.MESSAGE_REPORT_POWER_STATUS) { + mSinkDevicePowerStatus = params[0]; + } else if (srcAddress == HdmiCec.ADDR_TV) { + if (opcode == HdmiCec.MESSAGE_STANDBY) { + mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_STANDBY; + } else if (opcode == HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS) { + mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_ON; + } + } + super.handleMessage(srcAddress, dstAddress, opcode, params); + } + + @Override + public void handleHotplug(boolean connected) { + // If cable get disconnected sink device becomes unreachable. Switch the status + // to unknown, and query the status once the cable gets connected back. + if (!connected) { + mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_UNKNOWN; + } else { + queryTvPowerStatus(); + } + super.handleHotplug(connected); + } + + @Override + public boolean isSinkDeviceOn() { + return mSinkDevicePowerStatus == HdmiCec.POWER_STATUS_ON; + } +} diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java new file mode 100644 index 0000000..09ff3ca --- /dev/null +++ b/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.hdmi; + +/** + * Class for logical device of TV type. + */ +final class HdmiCecDeviceTv extends HdmiCecDevice { + private static final String TAG = "HdmiCecDeviceTv"; + + /** + * Constructor. + */ + public HdmiCecDeviceTv(HdmiCecService service, int type) { + super(service, type); + } + + public void initialize() { + // TODO: Do the initialization task for TV device here. + } +} diff --git a/services/core/java/com/android/server/hdmi/HdmiCecService.java b/services/core/java/com/android/server/hdmi/HdmiCecService.java index 0a7236c..aa496c5 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecService.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecService.java @@ -23,6 +23,7 @@ import android.hardware.hdmi.HdmiCecMessage; import android.hardware.hdmi.IHdmiCecListener; import android.hardware.hdmi.IHdmiCecService; import android.os.Binder; +import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.text.TextUtils; @@ -30,6 +31,7 @@ import android.util.Log; import android.util.SparseArray; import com.android.server.SystemService; +import libcore.util.EmptyArray; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -37,8 +39,6 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Locale; -import libcore.util.EmptyArray; - /** * Provides a service for sending and processing HDMI-CEC messages, and providing * the information on HDMI settings in general. @@ -65,7 +65,7 @@ public final class HdmiCecService extends SystemService { private static final String PERMISSION = "android.permission.HDMI_CEC"; - private static final byte[] EMPTY_PARAM = EmptyArray.BYTE; + static final byte[] EMPTY_PARAM = EmptyArray.BYTE; public HdmiCecService(Context context) { super(context); @@ -76,7 +76,12 @@ public final class HdmiCecService extends SystemService { @Override public void onStart() { mNativePtr = nativeInit(this); - publishBinderService(Context.HDMI_CEC_SERVICE, new BinderService()); + if (mNativePtr != 0) { + // TODO: Consider using a dedicated, configurable identifier for OSD name, maybe from + // Settings. It should be ASCII only, not a very long one (limited to 15 chars). + setOsdNameLocked(Build.MODEL); + publishBinderService(Context.HDMI_CEC_SERVICE, new BinderService()); + } } /** @@ -88,7 +93,6 @@ public final class HdmiCecService extends SystemService { // but better be handled in service by turning off the screen // or putting the device into suspend mode. List up such messages // and handle them here. - int type = HdmiCec.getTypeFromAddress(dstAddress); synchronized (mLock) { if (dstAddress == HdmiCec.ADDR_BROADCAST) { for (int i = 0; i < mLogicalDevices.size(); ++i) { @@ -96,6 +100,7 @@ public final class HdmiCecService extends SystemService { params); } } else { + int type = HdmiCec.getTypeFromAddress(dstAddress); HdmiCecDevice device = mLogicalDevices.get(type); if (device == null) { Log.w(TAG, "logical device not found. type: " + type); @@ -138,22 +143,6 @@ public final class HdmiCecService extends SystemService { } /** - * Called by native when a request for the device OSD name was received. - * The native part uses the return value to generate the message - * <Set Osd Name> in response. - */ - private byte[] getOsdName(int type) { - // TODO: Consider getting the OSD name from device name instead. - synchronized (mLock) { - HdmiCecDevice device = mLogicalDevices.get(type); - if (device != null) { - return device.getName().getBytes(Charset.forName("US-ASCII")); - } - } - return null; - } - - /** * Called by native when a request for the menu language of the device was * received. The native part uses the return value to generate the message * <Set Menu Language> in response. The language should be of @@ -174,8 +163,7 @@ public final class HdmiCecService extends SystemService { synchronized (mLock) { for (int i = 0; i < mLogicalDevices.size(); ++i) { HdmiCecDevice device = mLogicalDevices.valueAt(i); - pw.println("Device: name=" + device.getName() + - ", type=" + device.getType() + + pw.println("Device: type=" + device.getType() + ", active=" + device.isActiveSource()); } } @@ -205,6 +193,15 @@ public final class HdmiCecService extends SystemService { throw new IllegalArgumentException("Device not found"); } + // package-private. Used by HdmiCecDevice and its subclasses only. + void sendMessage(int type, int address, int opcode, byte[] params) { + nativeSendMessage(mNativePtr, type, address, opcode, params); + } + + private void setOsdNameLocked(String name) { + nativeSetOsdName(mNativePtr, name.getBytes(Charset.forName("US-ASCII"))); + } + private final class ListenerRecord implements IBinder.DeathRecipient { private final IHdmiCecListener mListener; private final int mType; @@ -248,8 +245,12 @@ public final class HdmiCecService extends SystemService { Log.e(TAG, "Logical address was not allocated"); return null; } else { - device = new HdmiCecDevice(type); - device.setName(HdmiCec.getDefaultDeviceName(address)); + device = HdmiCecDevice.create(HdmiCecService.this, type); + if (device == null) { + Log.e(TAG, "Device type not supported yet."); + return null; + } + device.initialize(); mLogicalDevices.put(type, device); } } @@ -272,18 +273,6 @@ public final class HdmiCecService extends SystemService { } @Override - public void setOsdName(IBinder b, String name) { - enforceAccessPermission(); - if (TextUtils.isEmpty(name)) { - throw new IllegalArgumentException("name must not be null"); - } - synchronized (mLock) { - HdmiCecDevice device = getLogicalDeviceLocked(b); - device.setName(name); - } - } - - @Override public void sendActiveSource(IBinder b) { enforceAccessPermission(); synchronized (mLock) { @@ -331,12 +320,11 @@ public final class HdmiCecService extends SystemService { } @Override - public void sendGiveDevicePowerStatus(IBinder b, int address) { + public boolean isTvOn(IBinder b) { enforceAccessPermission(); synchronized (mLock) { HdmiCecDevice device = getLogicalDeviceLocked(b); - nativeSendMessage(mNativePtr, device.getType(), address, - HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, EMPTY_PARAM); + return device.isSinkDeviceOn(); } } @@ -398,4 +386,5 @@ public final class HdmiCecService extends SystemService { private static native void nativeSendMessage(long handler, int deviceType, int destination, int opcode, byte[] params); private static native int nativeGetPhysicalAddress(long handler); + private static native void nativeSetOsdName(long handler, byte[] name); } diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java index faa5a43..d9e2b91 100644 --- a/services/core/java/com/android/server/notification/NotificationUsageStats.java +++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java @@ -20,7 +20,6 @@ import com.android.server.notification.NotificationManagerService.NotificationRe import android.os.SystemClock; import android.service.notification.StatusBarNotification; -import android.util.Log; import java.io.PrintWriter; import java.util.HashMap; @@ -250,21 +249,28 @@ public class NotificationUsageStats { */ public static class Aggregate { long numSamples; - long sum; - long avg; + double avg; + double sum2; + double var; public void addSample(long sample) { + // Welford's "Method for Calculating Corrected Sums of Squares" + // http://www.jstor.org/stable/1266577?seq=2 numSamples++; - sum += sample; - avg = sum / numSamples; + final double n = numSamples; + final double delta = sample - avg; + avg += (1.0 / n) * delta; + sum2 += ((n - 1) / n) * delta * delta; + final double divisor = numSamples == 1 ? 1.0 : n - 1.0; + var = sum2 / divisor; } @Override public String toString() { return "Aggregate{" + "numSamples=" + numSamples + - ", sum=" + sum + ", avg=" + avg + + ", var=" + var + '}'; } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 288e8e0..dd22b2d 100755 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -9214,9 +9214,20 @@ public class PackageManagerService extends IPackageManager.Stub { final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras; newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime; newPkgSetting.lastUpdateTime = System.currentTimeMillis(); + + // is the update attempting to change shared user? that isn't going to work... + if (oldPkgSetting.sharedUser != newPkgSetting.sharedUser) { + Slog.w(TAG, "Forbidding shared user change from " + oldPkgSetting.sharedUser + + " to " + newPkgSetting.sharedUser); + res.returnCode = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE; + updatedSettings = true; + } + } + + if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { + updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res); + updatedSettings = true; } - updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res); - updatedSettings = true; } if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index a388318..80c3c8e 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -2541,6 +2541,9 @@ public final class PowerManagerService extends com.android.server.SystemService @Override // Binder call public void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName, int uid) { + if (uid < 0) { + uid = Binder.getCallingUid(); + } acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null); } diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp index 61edda8..a00aaa8 100644 --- a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp +++ b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp @@ -20,7 +20,7 @@ #include "ScopedPrimitiveArray.h" -#include <cstring> +#include <string> #include <deque> #include <map> @@ -34,7 +34,6 @@ static struct { jmethodID handleMessage; jmethodID handleHotplug; jmethodID getActiveSource; - jmethodID getOsdName; jmethodID getLanguage; } gHdmiCecServiceClassInfo; @@ -84,6 +83,7 @@ public: void sendSetMenuLanguage(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr); void sendCecMessage(const cec_message_t& message); + void setOsdName(const char* name, size_t len); private: enum { @@ -156,6 +156,7 @@ private: std::deque<MessageEntry> mMessageQueue; uint16_t mPhysicalAddress; + std::string mOsdName; }; @@ -373,6 +374,10 @@ void HdmiCecHandler::sendCecMessage(const cec_message_t& message) { mDevice->send_message(mDevice, &message); } +void HdmiCecHandler::setOsdName(const char* name, size_t len) { + mOsdName.assign(name, min(len, CEC_MESSAGE_BODY_MAX_LENGTH - 1)); +} + // static void HdmiCecHandler::onReceived(const hdmi_event_t* event, void* arg) { HdmiCecHandler* handler = static_cast<HdmiCecHandler*>(arg); @@ -504,18 +509,9 @@ void HdmiCecHandler::handleRequestActiveSource() { } void HdmiCecHandler::handleGetOsdName(const cec_message_t& msg) { - cec_logical_address_t addr = msg.destination; - JNIEnv* env = AndroidRuntime::getJNIEnv(); - jbyteArray res = (jbyteArray) env->CallObjectMethod(mCallbacksObj, - gHdmiCecServiceClassInfo.getOsdName, - getDeviceType(addr)); - jbyte *name = env->GetByteArrayElements(res, NULL); - if (name != NULL) { - sendSetOsdName(addr, msg.initiator, reinterpret_cast<const char *>(name), - env->GetArrayLength(res)); - env->ReleaseByteArrayElements(res, name, JNI_ABORT); + if (!mOsdName.empty()) { + sendSetOsdName(msg.destination, msg.initiator, mOsdName.c_str(), mOsdName.length()); } - checkAndClearExceptionFromCallback(env, __FUNCTION__); } void HdmiCecHandler::handleGiveDeviceVendorID(const cec_message_t& msg) { @@ -562,8 +558,6 @@ static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj) { "handleHotplug", "(Z)V"); GET_METHOD_ID(gHdmiCecServiceClassInfo.getActiveSource, clazz, "getActiveSource", "()I"); - GET_METHOD_ID(gHdmiCecServiceClassInfo.getOsdName, clazz, - "getOsdName", "(I)[B"); GET_METHOD_ID(gHdmiCecServiceClassInfo.getLanguage, clazz, "getLanguage", "(I)Ljava/lang/String;"); @@ -603,6 +597,15 @@ static jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr return handler->getPhysicalAddress(); } +static void nativeSetOsdName(JNIEnv* env, jclass clazz, jlong handlerPtr, jbyteArray name) { + HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr); + jsize len = env->GetArrayLength(name); + if (len > 0) { + ScopedByteArrayRO namePtr(env, name); + handler->setOsdName(reinterpret_cast<const char *>(namePtr.get()), len); + } +} + static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ { "nativeInit", "(Lcom/android/server/hdmi/HdmiCecService;)J", @@ -615,6 +618,8 @@ static JNINativeMethod sMethods[] = { (void *)nativeRemoveLogicalAddress }, { "nativeGetPhysicalAddress", "(J)I", (void *)nativeGetPhysicalAddress }, + { "nativeSetOsdName", "(J[B)V", + (void *)nativeSetOsdName }, }; #define CLASS_PATH "com/android/server/hdmi/HdmiCecService" diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index ce205c0..8f2adc8 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -269,7 +269,7 @@ public final class SystemServer { private void createSystemContext() { ActivityThread activityThread = ActivityThread.systemMain(); mSystemContext = activityThread.getSystemContext(); - mSystemContext.setTheme(android.R.style.Theme_Holo); + mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); } private void startBootstrapServices() { diff --git a/tests/DynamicDrawableTest/lint.xml b/tests/DynamicDrawableTest/lint.xml deleted file mode 100644 index ee0eead..0000000 --- a/tests/DynamicDrawableTest/lint.xml +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<lint> -</lint>
\ No newline at end of file diff --git a/tests/DynamicDrawableTest/Android.mk b/tests/VectorDrawableTest/Android.mk index 5c51301..dd8a4d4 100644 --- a/tests/DynamicDrawableTest/Android.mk +++ b/tests/VectorDrawableTest/Android.mk @@ -19,7 +19,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_PACKAGE_NAME := DynamicDrawableTest +LOCAL_PACKAGE_NAME := VectorDrawableTest LOCAL_MODULE_TAGS := tests diff --git a/tests/DynamicDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml index 4ca3e3c..06effe2 100644 --- a/tests/DynamicDrawableTest/AndroidManifest.xml +++ b/tests/VectorDrawableTest/AndroidManifest.xml @@ -73,7 +73,7 @@ </intent-filter> </activity> - + <activity android:name="VectorCheckbox" android:label="On a Checkbox" > diff --git a/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png b/tests/VectorDrawableTest/res/drawable-hdpi/icon.png Binary files differindex 60fbdf5..60fbdf5 100644 --- a/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png +++ b/tests/VectorDrawableTest/res/drawable-hdpi/icon.png diff --git a/tests/DynamicDrawableTest/res/drawable/icon.png b/tests/VectorDrawableTest/res/drawable/icon.png Binary files differindex cb40a19..cb40a19 100644 --- a/tests/DynamicDrawableTest/res/drawable/icon.png +++ b/tests/VectorDrawableTest/res/drawable/icon.png diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml index 4f4b386..538993f 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml @@ -14,7 +14,7 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:trigger="state_checked" > + android:trigger="state_checked" android:versionCode="1" > <size android:height="64dp" diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml index 49906d17..49906d17 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml index 137049d..137049d 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml index cffb73f..cffb73f 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml index bcf3ae6..bcf3ae6 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml index 73ff5e2..73ff5e2 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml index 99d37ef..99d37ef 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml index f8a03d7..f8a03d7 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml index 09934de..09934de 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml index f17f67a..f17f67a 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml index a1a03be..8787b34 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml @@ -29,7 +29,7 @@ android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z" android:fill="#3388ff" android:stroke="#ff8833" - android:strokeWidth="1" + android:strokeWidth="1" android:rotation="0"/> <path android:name="spark" diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml index 89748d5..89748d5 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml index 43dda52..43dda52 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml index 0f1f149..0f1f149 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml index 6bc946f..6bc946f 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml index c9c8e8a..c9c8e8a 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml index 9427652..9427652 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml index 83dfbd2..83dfbd2 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml index 013254f..013254f 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml index aba7e5f..aba7e5f 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml index 8897181..8897181 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml index 2c7ebbd..2c7ebbd 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml index e4cf78c..e4cf78c 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml index cec12ba..cec12ba 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml index 5fe1fb6..5fe1fb6 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test01.xml b/tests/VectorDrawableTest/res/drawable/vector_test01.xml index 6beb9d8..6beb9d8 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_test01.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_test01.xml diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test02.xml b/tests/VectorDrawableTest/res/drawable/vector_test02.xml index 2c1a28e..2c1a28e 100644 --- a/tests/DynamicDrawableTest/res/drawable/vector_test02.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_test02.xml diff --git a/tests/DynamicDrawableTest/res/values/strings.xml b/tests/VectorDrawableTest/res/values/strings.xml index 64163c2..64163c2 100644 --- a/tests/DynamicDrawableTest/res/values/strings.xml +++ b/tests/VectorDrawableTest/res/values/strings.xml diff --git a/tests/DynamicDrawableTest/res/values/styles.xml b/tests/VectorDrawableTest/res/values/styles.xml index 460c0db..460c0db 100644 --- a/tests/DynamicDrawableTest/res/values/styles.xml +++ b/tests/VectorDrawableTest/res/values/styles.xml diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java index 1060d19..0b3ea4d 100644 --- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java @@ -60,7 +60,6 @@ public class VectorCheckbox extends Activity { CheckBox checkBox = new CheckBox(this); bArray[i] = checkBox; checkBox.setWidth(200); - checkBox.setWidth(200); checkBox.setButtonDrawable(icon[i]); container.addView(checkBox); } diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java index 0ae4b6d..88ae398 100644 --- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java @@ -59,7 +59,6 @@ public class VectorDrawable01 extends Activity implements View.OnClickListener { Button button = new Button(this); bArray[i] = button; button.setWidth(200); - button.setWidth(200); button.setBackgroundResource(icon[i]); container.addView(button); button.setOnClickListener(this); diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java index a00bc5e..a00bc5e 100644 --- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java index 9e8ea75..3929298 100644 --- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java @@ -74,7 +74,6 @@ public class VectorDrawablePerformance extends Activity implements View.OnClickL for (int i = 0; i < icon.length; i++) { Button button = new Button(this); button.setWidth(200); - button.setWidth(200); button.setBackgroundResource(icon[i]); container.addView(button); button.setOnClickListener(this); diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java index 9d3eded..9d3eded 100644 --- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java index 704d3d7..704d3d7 100644 --- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java index 3430192..3430192 100644 --- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java |