Merge "Import translations. DO NOT MERGE"
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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
 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 @@
 
 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 @@
     }
 
     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..20e7311 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4701,42 +4701,31 @@
     }
 
     /**
-     * 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}.
      *
      * @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 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 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 @@
             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 @@
         return isInLockTaskMode;
     }
 
-    public void setRecentsLabel(IBinder token, CharSequence recentsLabel) 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);
-        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
-    {
-        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 @@
                                         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 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 @@
     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 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.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 @@
             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 @@
         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 @@
         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 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 @@
     }
 
     /**
-     * Send &lt;GiveDevicePowerStatus&gt; 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 @@
      * @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 @@
 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 @@
                 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 @@
     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 @@
                 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 @@
         return INVALID_LISTENER_KEY;
     }
 
-
     private String getNsdServiceInfoType(NsdServiceInfo s) {
         if (s == null) return "?";
         return s.getServiceType();
@@ -449,14 +452,18 @@
      * 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 @@
         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 @@
      *
      * @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 @@
      * <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 @@
 
         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 @@
      * {@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 @@
      *
      * @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 @@
         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/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 4180860..2ef5b66 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -713,10 +713,9 @@
             public void clearPassword() throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
-                String _result;
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_clearPassword, _data, _reply, 0);
+                    mRemote.transact(Stub.TRANSACTION_clearPassword, _data, _reply, IBinder.FLAG_ONEWAY);
                     _reply.readException();
                 } finally {
                     _reply.recycle();
@@ -724,6 +723,38 @@
                 }
             }
 
+            public void setField(String field, String data) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(field);
+                    _data.writeString(data);
+                    mRemote.transact(Stub.TRANSACTION_setField, _data, _reply, IBinder.FLAG_ONEWAY);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            public String getField(String field) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                String _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(field);
+                    mRemote.transact(Stub.TRANSACTION_getField, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.readString();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
+
             public StorageVolume[] getVolumeList() throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
@@ -882,6 +913,10 @@
 
         static final int TRANSACTION_clearPassword = IBinder.FIRST_CALL_TRANSACTION + 37;
 
+        static final int TRANSACTION_setField = IBinder.FIRST_CALL_TRANSACTION + 38;
+
+        static final int TRANSACTION_getField = IBinder.FIRST_CALL_TRANSACTION + 39;
+
         /**
          * Cast an IBinder object into an IMountService interface, generating a
          * proxy if needed.
@@ -1255,6 +1290,22 @@
                     reply.writeNoException();
                     return true;
                 }
+                case TRANSACTION_setField: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String field = data.readString();
+                    String contents = data.readString();
+                    setField(field, contents);
+                    reply.writeNoException();
+                    return true;
+                }
+                case TRANSACTION_getField: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String field = data.readString();
+                    String contents = getField(field);
+                    reply.writeNoException();
+                    reply.writeString(contents);
+                    return true;
+                }
             }
             return super.onTransact(code, data, reply, flags);
         }
@@ -1504,4 +1555,18 @@
      * Securely clear password from vold
      */
     public void clearPassword() throws RemoteException;
+
+    /**
+     * Set a field in the crypto header.
+     * @param field field to set
+     * @param contents contents to set in field
+     */
+    public void setField(String field, String contents) throws RemoteException;
+
+    /**
+     * Gets a field from the crypto header.
+     * @param field field to get
+     * @return contents of field
+     */
+    public String getField(String field) throws RemoteException;
 }
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 @@
     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 @@
      * @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 @@
      * @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 @@
      * 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 (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;
+        }
 
-        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");
-
-        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 @@
         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 @@
                     | (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 @@
             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 @@
     }
 
     /**
-     * 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 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    // 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 @@
     }
 
     /**
-     * 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 @@
 
     /**
      * 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 @@
      * 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 @@
     }
 
     /**
-     * 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 @@
         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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
      * 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 @@
         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 @@
      */
     View() {
         mResources = null;
+        mRenderNode = RenderNode.create(getClass().getName());
     }
 
     public String toString() {
@@ -4847,10 +4746,10 @@
 
             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 @@
                         }
 
                         removeTapCallback();
+                    } else {
+                        clearHotspot(R.attr.state_pressed);
                     }
                     break;
 
@@ -9204,6 +9105,7 @@
      */
     private void removeUnsetPressCallback() {
         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
+            clearHotspot(R.attr.state_pressed);
             setPressed(false);
             removeCallbacks(mUnsetPressedState);
         }
@@ -9682,21 +9584,10 @@
      * @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 @@
      * @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 @@
         }
     }
 
-    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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getRotation() {
-        return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
+        return mRenderNode.getRotation();
     }
 
     /**
@@ -9905,21 +9713,13 @@
      * @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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getRotationY() {
-        return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
+        return mRenderNode.getRotationY();
     }
 
     /**
@@ -9957,20 +9757,12 @@
      * @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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getRotationX() {
-        return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
+        return mRenderNode.getRotationX();
     }
 
     /**
@@ -10008,20 +9800,12 @@
      * @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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getScaleX() {
-        return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
+        return mRenderNode.getScaleX();
     }
 
     /**
@@ -10051,20 +9835,12 @@
      * @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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getScaleY() {
-        return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
+        return mRenderNode.getScaleY();
     }
 
     /**
@@ -10094,20 +9870,12 @@
      * @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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getPivotX() {
-        return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
+        return mRenderNode.getPivotX();
     }
 
     /**
@@ -10144,23 +9912,12 @@
      * @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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getPivotY() {
-        return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
+        return mRenderNode.getPivotY();
     }
 
     /**
@@ -10196,23 +9953,12 @@
      * @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 @@
             } else {
                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
                 invalidateViewProperty(true, false);
-                if (mRenderNode != null) {
-                    mRenderNode.setAlpha(getFinalAlpha());
-                }
+                mRenderNode.setAlpha(getFinalAlpha());
             }
         }
     }
@@ -10317,9 +10061,7 @@
                 return true;
             } else {
                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
-                if (mRenderNode != null) {
-                    mRenderNode.setAlpha(getFinalAlpha());
-                }
+                mRenderNode.setAlpha(getFinalAlpha());
             }
         }
         return false;
@@ -10340,9 +10082,7 @@
             mTransformationInfo.mTransitionAlpha = alpha;
             mPrivateFlags &= ~PFLAG_ALPHA_SET;
             invalidateViewProperty(true, false);
-            if (mRenderNode != null) {
-                mRenderNode.setAlpha(getFinalAlpha());
-            }
+            mRenderNode.setAlpha(getFinalAlpha());
         }
     }
 
@@ -10389,9 +10129,7 @@
      */
     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 @@
             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 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 @@
             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 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 @@
             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 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 @@
             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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getX() {
-        return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
+        return mLeft + getTranslationX();
     }
 
     /**
@@ -10673,7 +10381,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getY() {
-        return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
+        return mTop + getTranslationY();
     }
 
     /**
@@ -10697,7 +10405,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getTranslationX() {
-        return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
+        return mRenderNode.getTranslationX();
     }
 
     /**
@@ -10711,21 +10419,12 @@
      * @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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getTranslationY() {
-        return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
+        return mRenderNode.getTranslationY();
     }
 
     /**
@@ -10753,20 +10452,12 @@
      * @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 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getTranslationZ() {
-        return mTransformationInfo != null ? mTransformationInfo.mTranslationZ : 0;
+        return mRenderNode.getTranslationZ();
     }
 
     /**
@@ -10786,20 +10477,12 @@
      * @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 @@
             }
             mOutline.set(outline);
         }
-
-        if (mRenderNode != null) {
-            mRenderNode.setOutline(mOutline);
-        }
+        mRenderNode.setOutline(mOutline);
     }
 
     /**
@@ -10907,9 +10587,7 @@
             } else {
                 mPrivateFlags3 &= ~PFLAG3_CLIP_TO_OUTLINE;
             }
-            if (mRenderNode != null) {
-                mRenderNode.setClipToOutline(clipToOutline);
-            }
+            mRenderNode.setClipToOutline(clipToOutline);
         }
     }
 
@@ -10920,11 +10598,9 @@
      */
     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 @@
      * @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 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 @@
 
             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 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 @@
 
             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 @@
             }
 
             // Damage the entire IsolatedZVolume recieving this view's shadow.
-            if (getTranslationZ() != 0) {
+            if (isHardwareAccelerated() && getTranslationZ() != 0) {
                 damageShadowReceiver();
             }
         }
@@ -11553,7 +11223,9 @@
      * 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 @@
         } else {
             damageInParent();
         }
-        if (invalidateParent && getTranslationZ() != 0) {
+        if (isHardwareAccelerated() && invalidateParent && getTranslationZ() != 0) {
             damageShadowReceiver();
         }
     }
@@ -11581,7 +11253,7 @@
             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 @@
     }
 
     /**
+     * @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 @@
      * @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 @@
     }
 
     /**
-     * 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 @@
                             alpha = t.getAlpha();
                         }
                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
-                            displayList.setStaticMatrix(t.getMatrix());
+                            renderNode.setStaticMatrix(t.getMatrix());
                         }
                     }
                 }
@@ -14617,23 +14293,9 @@
                         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 @@
             }
             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 @@
             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 @@
             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 @@
      *
      * @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 @@
                         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 @@
      *
      * @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 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 @@
          * @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 @@
         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 @@
      * @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 @@
                 }
             }
             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/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b617f68..a35c28e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -678,13 +678,13 @@
         mAttachInfo.mHardwareAccelerationRequested = false;
 
         // Don't enable hardware acceleration when the application is in compatibility mode
-        if (false && mTranslator != null) return;
+        if (mTranslator != null) return;
 
         // Try to enable hardware acceleration if requested
         final boolean hardwareAccelerated =
                 (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
 
-        if (true || hardwareAccelerated) {
+        if (hardwareAccelerated) {
             if (!HardwareRenderer.isAvailable()) {
                 return;
             }
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 @@
                 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 @@
         }
 
         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 @@
         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 @@
     }
 
     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 @@
                     "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/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index f9e5569..ac3274d 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -545,6 +545,7 @@
 
         public boolean isCurrentProfile(int userId) {
             synchronized (this) {
+                if (userId == mCurrentUserId) return true;
                 for (int i = 0; i < mCurrentProfileIds.length; i++) {
                     if (userId == mCurrentProfileIds[i]) return true;
                 }
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 @@
             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 @@
             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/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index b9bc54d..4504910 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -564,12 +564,37 @@
         }
     }
 
+    private void updateCryptoUserInfo() {
+        int userId = getCurrentOrCallingUserId();
+        if (userId != UserHandle.USER_OWNER) {
+            return;
+        }
+
+        final String ownerInfo = isOwnerInfoEnabled() ? getOwnerInfo(userId) : "";
+
+        IBinder service = ServiceManager.getService("mount");
+        if (service == null) {
+            Log.e(TAG, "Could not find the mount service to update the user info");
+            return;
+        }
+
+        IMountService mountService = IMountService.Stub.asInterface(service);
+        try {
+            Log.d(TAG, "Setting owner info");
+            mountService.setField("OwnerInfo", ownerInfo);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error changing user info", e);
+        }
+    }
+
     public void setOwnerInfo(String info, int userId) {
         setString(LOCK_SCREEN_OWNER_INFO, info, userId);
+        updateCryptoUserInfo();
     }
 
     public void setOwnerInfoEnabled(boolean enabled) {
         setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled);
+        updateCryptoUserInfo();
     }
 
     public String getOwnerInfo(int userId) {
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 @@
 
 /*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 @@
     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 @@
     }
 
     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..d079349c 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -69,7 +69,7 @@
 }
 
 // ----------------------------------------------------------------------------
-// RenderProperties
+// RenderProperties - setters
 // ----------------------------------------------------------------------------
 
 static void android_view_RenderNode_setCaching(JNIEnv* env,
@@ -209,22 +209,6 @@
     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 @@
     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 @@
     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 @@
     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 @@
     { "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 @@
     { "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/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2a4d872..3857cd1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2585,6 +2585,13 @@
         android:description="@string/permdesc_accessNetworkConditions"
         android:protectionLevel="signature|system" />
 
+    <!-- Allows an application to provision and access DRM certificates
+         @hide This is not a third-party API (intended for system apps). -->
+    <permission android:name="android.permission.ACCESS_DRM_CERTIFICATES"
+        android:label="@string/permlab_accessDrmCertificates"
+        android:description="@string/permdesc_accessDrmCertificates"
+        android:protectionLevel="signature|system" />
+
     <!-- The system process is explicitly the only one allowed to launch the
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
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"
-                android:layout_width="wrap_content"
-                android:layout_gravity="start"
-                android:layout_weight="1"
-                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"
-                android:layout_weight="1"
+                android:layout_height="wrap_content"
+                android:layout_gravity="start"
+                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" />
+            <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"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                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 @@
     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/strings.xml b/core/res/res/values/strings.xml
index 3a4f059..902aea8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2002,6 +2002,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_setInputCalibration">Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_accessDrmCertificates">access DRM certificates</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_accessDrmCertificates">Allows an application to provision and use DRM certficates. Should never be needed for normal apps.</string>
+
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
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 @@
     <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 @@
     </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 @@
         <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 @@
     <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 d39a1f8..50f1ca6 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -154,7 +154,7 @@
         <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 @@
 
         <!-- 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 @@
 
         <!-- 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 @@
          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>
+&lt;service android:name=".provider.SampleMediaRouteProviderService"
+    android:label="&#64;string/sample_media_route_provider_service"
+    android:process=":mrp"&gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name="android.media.MediaRouteProviderService" /&gt;
+    &lt;/intent-filter&gt;
+&lt;/service&gt;
+</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 {
+
+    &#64;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}
+    &mdash; 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}
+    &mdash; 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} &mdash; 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&lt;IntentFilter&gt; CONTROL_FILTERS_BASIC;
+    static {
+        IntentFilter videoPlayback = new IntentFilter();
+        <strong>videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);</strong>
+        CONTROL_FILTERS_BASIC = new ArrayList&lt;IntentFilter&gt;();
+        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&lt;IntentFilter&gt; 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&lt;IntentFilter&gt;();
+        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&lt;IntentFilter&gt; 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&lt;IntentFilter&gt;();
+        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()}
+    &mdash; 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()} &mdash; Sends specific playback commands to the receiving device.</li>
+  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSetVolume
+    onSetVolume()} &mdash; 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()} &mdash; 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()} &mdash; Called when an application unselects a route.</li>
+  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onRelease onRelease()}
+    &mdash; 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 {
+    ...
+
+    &#64;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 @@
       <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 @@
   (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 @@
     CATEGORY_LIVE_VIDEO} &mdash; 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} &mdash; 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} &mdash; 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 @@
 <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 @@
 <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 @@
 
 <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
new file mode 100644
index 0000000..60cc29a
--- /dev/null
+++ b/docs/html/images/mediarouter/media-route-provider-framework.png
Binary files differ
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
new file mode 100644
index 0000000..d82ea05
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist
Binary files differ
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
new file mode 100644
index 0000000..3435e35
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png
Binary files differ
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
new file mode 100644
index 0000000..07791df
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist
Binary files differ
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
new file mode 100644
index 0000000..d6e3e95
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist
new file mode 100644
index 0000000..ffd8212
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png
new file mode 100644
index 0000000..d6e3e95
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png
Binary files differ
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 @@
  * 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 @@
  * The vector drawable has 6 elements:
  * <p/>
  * <dl>
- * <dt><code>&lt;vector></code></dt><dd>
- * The attribute <code>android:trigger</code> which defines a state change that
+ * <dt><code>&lt;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>&lt;size></code></dt>
  * <dd>Used to defined the intrinsic Width Height size of the drawable using
  * <code>android:width</code> and <code>android:height</code> </dd>
@@ -494,6 +496,16 @@
                 }  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 @@
 class AndroidRuntime
 {
 public:
-    AndroidRuntime();
+    AndroidRuntime(char* argBlockStart, size_t argBlockSize);
     virtual ~AndroidRuntime();
 
     enum StartMode {
@@ -44,6 +44,8 @@
         Tool,
     };
 
+    void setArgv0(const char* argv0);
+
     /**
      * Register a set of methods in the specified class.
      */
@@ -120,6 +122,8 @@
 
     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 @@
 
 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 @@
         , 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 @@
         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 @@
             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 @@
         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 @@
             }
 
             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 @@
         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 @@
         return mPrimitiveFields.mMatrixFlags;
     }
 
-    const Matrix4* getTransformMatrix() const {
+    const SkMatrix* getTransformMatrix() const {
         return mComputedFields.mTransformMatrix;
     }
 
@@ -481,13 +481,11 @@
         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 @@
          * 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 @@
      * 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/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index c016d08..440653a 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -1,4 +1,4 @@
- /*
+/*
  * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,7 +27,6 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.util.Log;
-import android.content.Context;
 
 /**
  * MediaDrm can be used to obtain keys for decrypting protected media streams, in
@@ -98,6 +97,8 @@
 
     private final static String TAG = "MediaDrm";
 
+    private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
+
     private EventHandler mEventHandler;
     private OnEventListener mOnEventListener;
 
@@ -152,7 +153,7 @@
     }
 
     private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid,
-                                                                      String mimeType);
+            String mimeType);
 
     /**
      * Instantiate a MediaDrm object
@@ -176,7 +177,7 @@
          * It's easier to create it here than in C++.
          */
         native_setup(new WeakReference<MediaDrm>(this),
-                     getByteArrayFromUUID(uuid));
+                getByteArrayFromUUID(uuid));
     }
 
     /**
@@ -285,7 +286,7 @@
      * the cookie passed to native_setup().)
      */
     private static void postEventFromNative(Object mediadrm_ref,
-                                            int eventType, int extra, Object obj)
+            int eventType, int extra, Object obj)
     {
         MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get();
         if (md == null) {
@@ -385,9 +386,8 @@
      * problem with the certifcate
      */
     public native KeyRequest getKeyRequest(byte[] scope, byte[] init,
-                                           String mimeType, int keyType,
-                                           HashMap<String, String> optionalParameters)
-        throws NotProvisionedException;
+            String mimeType, int keyType, HashMap<String, String> optionalParameters)
+            throws NotProvisionedException;
 
 
     /**
@@ -411,7 +411,7 @@
      * @throws ResourceBusyException if required resources are in use
      */
     public native byte[] provideKeyResponse(byte[] scope, byte[] response)
-        throws NotProvisionedException, DeniedByServerException;
+            throws NotProvisionedException, DeniedByServerException;
 
 
     /**
@@ -478,7 +478,7 @@
     }
 
     private native ProvisionRequest getProvisionRequestNative(int certType,
-                                                              String certAuthority);
+            String certAuthority);
 
     /**
      * After a provision response is received by the app, it is provided to the DRM
@@ -491,12 +491,12 @@
      * server rejected the request
      */
     public void provideProvisionResponse(byte[] response)
-        throws DeniedByServerException {
+            throws DeniedByServerException {
         provideProvisionResponseNative(response);
     }
 
     private native Certificate provideProvisionResponseNative(byte[] response)
-        throws DeniedByServerException;
+            throws DeniedByServerException;
 
     /**
      * A means of enforcing limits on the number of concurrent streams per subscriber
@@ -583,23 +583,22 @@
 
 
     private static final native void setCipherAlgorithmNative(MediaDrm drm, byte[] sessionId,
-                                                              String algorithm);
+            String algorithm);
 
     private static final native void setMacAlgorithmNative(MediaDrm drm, byte[] sessionId,
-                                                           String algorithm);
+            String algorithm);
 
     private static final native byte[] encryptNative(MediaDrm drm, byte[] sessionId,
-                                                     byte[] keyId, byte[] input, byte[] iv);
+            byte[] keyId, byte[] input, byte[] iv);
 
     private static final native byte[] decryptNative(MediaDrm drm, byte[] sessionId,
-                                                     byte[] keyId, byte[] input, byte[] iv);
+            byte[] keyId, byte[] input, byte[] iv);
 
     private static final native byte[] signNative(MediaDrm drm, byte[] sessionId,
-                                                  byte[] keyId, byte[] message);
+            byte[] keyId, byte[] message);
 
     private static final native boolean verifyNative(MediaDrm drm, byte[] sessionId,
-                                                     byte[] keyId, byte[] message,
-                                                     byte[] signature);
+            byte[] keyId, byte[] message, byte[] signature);
 
     /**
      * In addition to supporting decryption of DASH Common Encrypted Media, the
@@ -629,7 +628,7 @@
         private byte[] mSessionId;
 
         CryptoSession(MediaDrm drm, byte[] sessionId,
-                      String cipherAlgorithm, String macAlgorithm)
+                String cipherAlgorithm, String macAlgorithm)
         {
             mSessionId = sessionId;
             mDrm = drm;
@@ -704,8 +703,7 @@
      * "algorithms".
      */
     public CryptoSession getCryptoSession(byte[] sessionId,
-                                          String cipherAlgorithm,
-                                          String macAlgorithm)
+            String cipherAlgorithm, String macAlgorithm)
     {
         return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm);
     }
@@ -751,11 +749,11 @@
      * @hide - not part of the public API at this time
      */
     public CertificateRequest getCertificateRequest(int certType,
-                                                    String certAuthority)
+            String certAuthority)
     {
         ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority);
         return new CertificateRequest(provisionRequest.getData(),
-                                      provisionRequest.getDefaultUrl());
+                provisionRequest.getDefaultUrl());
     }
 
     /**
@@ -800,18 +798,16 @@
      * @hide - not part of the public API at this time
      */
     public Certificate provideCertificateResponse(byte[] response)
-        throws DeniedByServerException {
+            throws DeniedByServerException {
         return provideProvisionResponseNative(response);
     }
 
     private static final native byte[] signRSANative(MediaDrm drm, byte[] sessionId,
-                                                     String algorithm, byte[] wrappedKey,
-                                                     byte[] message);
+            String algorithm, byte[] wrappedKey, byte[] message);
 
     /**
      * Sign data using an RSA key
      *
-     * @param context the app context
      * @param sessionId a sessionId obtained from openSession on the MediaDrm object
      * @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
      * @param wrappedKey - the wrapped (encrypted) RSA private key obtained
@@ -820,7 +816,8 @@
      *
      * @hide - not part of the public API at this time
      */
-    public byte[] signRSA(Context context, byte[] sessionId, String algorithm, byte[] wrappedKey, byte[] message) {
+    public byte[] signRSA(byte[] sessionId, String algorithm,
+            byte[] wrappedKey, byte[] message) {
         return signRSANative(this, sessionId, algorithm, wrappedKey, message);
     }
 
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 1dbaa3a..7c45682 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -570,7 +570,7 @@
     FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
     GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
     GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
-    gFields.certificateClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
+    gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
 
     FIND_CLASS(clazz, "java/util/ArrayList");
     GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
@@ -595,13 +595,13 @@
     GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
 
     FIND_CLASS(clazz, "java/util/HashMap");
-    gFields.hashmapClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
+    gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
 
     FIND_CLASS(clazz, "java/lang/String");
-    gFields.stringClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
+    gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
 
     FIND_CLASS(clazz, "java/util/ArrayList");
-    gFields.arraylistClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
+    gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
 }
 
 static void android_media_MediaDrm_native_setup(
diff --git a/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java b/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java
index d971afb..0a2897f 100644
--- a/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java
+++ b/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java
@@ -16,7 +16,6 @@
 
 package com.android.mediadrm.signer;
 
-import android.content.Context;
 import android.media.MediaDrm;
 import android.media.DeniedByServerException;
 
@@ -37,7 +36,7 @@
      * server
      */
     public final static class CertificateRequest {
-        private MediaDrm.CertificateRequest mCertRequest;
+        private final MediaDrm.CertificateRequest mCertRequest;
 
         CertificateRequest(MediaDrm.CertificateRequest certRequest) {
             mCertRequest = certRequest;
@@ -65,7 +64,7 @@
      * with a certificate.
      */
     public final static class Certificate {
-        private MediaDrm.Certificate mCertificate;
+        private final MediaDrm.Certificate mCertificate;
 
         Certificate(MediaDrm.Certificate certificate) {
             mCertificate = certificate;
@@ -97,7 +96,7 @@
      * the chain of authority.
      */
     public static CertificateRequest getCertificateRequest(MediaDrm drm, int certType,
-                                                           String certAuthority) {
+            String certAuthority) {
         return new CertificateRequest(drm.getCertificateRequest(certType, certAuthority));
     }
 
@@ -117,14 +116,13 @@
      * server rejected the request
      */
     public static Certificate provideCertificateResponse(MediaDrm drm, byte[] response)
-        throws DeniedByServerException {
+            throws DeniedByServerException {
         return new Certificate(drm.provideCertificateResponse(response));
     }
 
     /**
      * Sign data using an RSA key
      *
-     * @param context the App context
      * @param drm the MediaDrm object
      * @param sessionId a sessionId obtained from openSession on the MediaDrm object
      * @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
@@ -132,8 +130,8 @@
      * from provideCertificateResponse
      * @param message the data for which a signature is to be computed
      */
-    public static byte[] signRSA(Context context, MediaDrm drm, byte[] sessionId,
-                                 String algorithm, byte[] wrappedKey, byte[] message) {
-        return drm.signRSA(context, sessionId, algorithm, wrappedKey, message);
+    public static byte[] signRSA(MediaDrm drm, byte[] sessionId,
+            String algorithm, byte[] wrappedKey, byte[] message) {
+        return drm.signRSA(sessionId, algorithm, wrappedKey, message);
     }
 }
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/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml
index 8b157b4..8b423ab 100644
--- a/packages/InputDevices/res/values-da/strings.xml
+++ b/packages/InputDevices/res/values-da/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovensk"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Tyrkisk"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainsk"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabisk"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Græsk"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebræisk"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauisk"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spansk (latinamerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml
index 7e9b386..b7ec183 100644
--- a/packages/InputDevices/res/values-fi/strings.xml
+++ b/packages/InputDevices/res/values-fi/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"sloveeni"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"turkki"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukraina"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabia"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"kreikka"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"heprea"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"liettua"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"espanja (Latinalainen Amerikka)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml
index 9000405..18600ed 100644
--- a/packages/InputDevices/res/values-fr-rCA/strings.xml
+++ b/packages/InputDevices/res/values-fr-rCA/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovène"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turc"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainien"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabe"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grec"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hébreu"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituanien"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espagnol (latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ms-rMY/strings.xml b/packages/InputDevices/res/values-ms-rMY/strings.xml
index b26a633..32041d0 100644
--- a/packages/InputDevices/res/values-ms-rMY/strings.xml
+++ b/packages/InputDevices/res/values-ms-rMY/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Bahasa Slovenia"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Bahasa Turki"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Bahasa Ukraine"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Bahasa Arab"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Bahasa Greek"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Bahasa Ibrani"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Bahasa Lithuania"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Bahasa Sepanyol (Latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 828a45f..f84252a 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Słoweński"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turecki"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraiński"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabski"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"grecki"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"hebrajski"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litewski"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"hiszpański (Ameryka Łacińska)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml
index c61455d..151c11d 100644
--- a/packages/InputDevices/res/values-ro/strings.xml
+++ b/packages/InputDevices/res/values-ro/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenă"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turcă"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraineană"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabă"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greacă"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ebraică"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituaniană"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spaniolă (America Latină)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index 8b93723..585a215 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словенский"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"турецкий"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"украинский"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Арабский"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Греческий"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Иврит"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовский"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Испанский (Латинская Америка)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml
index ec511b3..d14c204 100644
--- a/packages/InputDevices/res/values-sk/strings.xml
+++ b/packages/InputDevices/res/values-sk/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"slovinské"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"turecké"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinské"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabčina"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Gréčtina"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrejčina"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litovčina"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Španielčina (Latinská Amerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index df9a280..d828e78 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovence"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Türkçe"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraynaca"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arapça"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Yunanca"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"İbranice"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litvanca"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"İspanyolca (Latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml
index e055ce2..8d76f92 100644
--- a/packages/InputDevices/res/values-zh-rCN/strings.xml
+++ b/packages/InputDevices/res/values-zh-rCN/strings.xml
@@ -34,14 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"斯洛文尼亚语"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"土耳其语"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"乌克兰语"</string>
-    <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
-    <skip />
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"阿拉伯语"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"希腊语"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"希伯来语"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"立陶宛语"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"西班牙语(拉丁美洲)"</string>
 </resources>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index 19eb4c5..c775467 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -75,7 +75,7 @@
     <string name="keyguard_accessibility_transport_thumbs_down_description" msgid="8101433677192177861">"Bài hát được đánh dấu không thích"</string>
     <string name="keyguard_accessibility_transport_heart_description" msgid="2336943232474689887">"Trái tim"</string>
     <string name="keyguard_accessibility_show_bouncer" msgid="5425837272418176176">"Mở khóa để tiếp tục"</string>
-    <string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"Quá trình khởi chạy bị hủy"</string>
+    <string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"Quá trình chạy bị hủy"</string>
     <string name="keyguard_accessibility_delete_widget_start" msgid="4096550552634391451">"Thả <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> để xóa."</string>
     <string name="keyguard_accessibility_delete_widget_end" msgid="508833506780909393">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> sẽ không bị xóa."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
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/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index f5ce222..96da21f 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -28,21 +28,29 @@
         android:layout_gravity="top|center_horizontal"
         android:background="#e6444444">
         <ImageView
-            android:id="@+id/activity_icon"
-            android:layout_width="@dimen/recents_task_view_icon_size"
-            android:layout_height="@dimen/recents_task_view_icon_size"
-            android:layout_gravity="top|left"
+            android:id="@+id/application_icon"
+            android:layout_width="@dimen/recents_task_view_application_icon_size"
+            android:layout_height="@dimen/recents_task_view_application_icon_size"
+            android:layout_gravity="center_vertical|left"
             android:padding="8dp" />
         <TextView
             android:id="@+id/activity_description"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical|left"
-            android:layout_marginLeft="@dimen/recents_task_view_icon_size"
+            android:layout_marginLeft="@dimen/recents_task_view_application_icon_size"
+            android:layout_marginRight="@dimen/recents_task_view_activity_icon_size"
             android:textSize="24sp"
             android:textColor="#ffffffff"
             android:text="@string/recents_empty_message"
             android:fontFamily="sans-serif-thin" />
+        <ImageView
+            android:id="@+id/activity_icon"
+            android:layout_width="@dimen/recents_task_view_activity_icon_size"
+            android:layout_height="@dimen/recents_task_view_activity_icon_size"
+            android:layout_gravity="center_vertical|right"
+            android:padding="12dp"
+            android:visibility="invisible" />
     </com.android.systemui.recents.views.TaskBarView>
 </com.android.systemui.recents.views.TaskView>
 
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/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 38e1083..1c6d5ad 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -230,8 +230,11 @@
     <!-- Default distance from each snap target that GlowPadView considers a "hit" -->
     <dimen name="glowpadview_inner_radius">15dip</dimen>
 
-    <!-- The size of the icon in the recents task view. -->
-    <dimen name="recents_task_view_icon_size">60dp</dimen>
+    <!-- The size of the application icon in the recents task view. -->
+    <dimen name="recents_task_view_application_icon_size">60dp</dimen>
+
+    <!-- The size of the activity icon in the recents task view. -->
+    <dimen name="recents_task_view_activity_icon_size">60dp</dimen>
 
     <!-- Space below the notification stack -->
     <dimen name="notification_stack_margin_bottom">0dp</dimen>
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.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 @@
         }
         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/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 227e19d..8543b97 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -23,35 +23,26 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
-import android.graphics.Paint;
 import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.View;
 import android.view.WindowManager;
 import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SystemUI;
 
 import java.util.List;
 
@@ -113,6 +104,7 @@
     final static String sRecentsService = "com.android.systemui.recents.RecentsService";
 
     Context mContext;
+    SystemServicesProxy mSystemServicesProxy;
 
     // Recents service binding
     Messenger mService = null;
@@ -127,6 +119,7 @@
 
     public AlternateRecentsComponent(Context context) {
         mContext = context;
+        mSystemServicesProxy = new SystemServicesProxy(context);
         mMessenger = new Messenger(new RecentsMessageHandler());
     }
 
@@ -219,17 +212,16 @@
 
     /** Loads the first task thumbnail */
     Bitmap loadFirstTaskThumbnail() {
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
-                ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_PROFILES,
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
                 UserHandle.CURRENT.getIdentifier());
         for (ActivityManager.RecentTaskInfo t : tasks) {
             // Skip tasks in the home stack
-            if (am.isInHomeStack(t.persistentId)) {
+            if (ssp.isInHomeStack(t.persistentId)) {
                 return null;
             }
 
-            Bitmap thumbnail = am.getTaskTopThumbnail(t.persistentId);
+            Bitmap thumbnail = ssp.getTaskThumbnail(t.persistentId);
             return thumbnail;
         }
         return null;
@@ -237,13 +229,12 @@
 
     /** Returns whether there is a first task */
     boolean hasFirstTask() {
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
-                ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_PROFILES,
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
                 UserHandle.CURRENT.getIdentifier());
         for (ActivityManager.RecentTaskInfo t : tasks) {
             // Skip tasks in the home stack
-            if (am.isInHomeStack(t.persistentId)) {
+            if (ssp.isInHomeStack(t.persistentId)) {
                 continue;
             }
 
@@ -294,8 +285,8 @@
 
         // If Recents is the front most activity, then we should just communicate with it directly
         // to launch the first task or dismiss itself
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RunningTaskInfo> tasks = ssp.getRunningTasks(1);
         if (!tasks.isEmpty()) {
             ComponentName topActivity = tasks.get(0).topActivity;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 2b08141..8c5c8fa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -31,6 +31,12 @@
             public static final boolean EnableToggleNewRecentsActivity = false;
             // This disables the bitmap and icon caches to
             public static final boolean DisableBackgroundCache = false;
+            // For debugging, this enables us to create mock recents tasks
+            public static final boolean EnableSystemServicesProxy = false;
+            // For debugging, this defines the number of mock recents packages to create
+            public static final int SystemServicesProxyMockPackageCount = 12;
+            // For debugging, this defines the number of mock recents tasks to create
+            public static final int SystemServicesProxyMockTaskCount = 75;
 
             // Timing certain paths
             public static final String TimeRecentsStartupKey = "startup";
@@ -73,8 +79,6 @@
         public static class RecentsTaskLoader {
             // XXX: This should be calculated on the first load
             public static final int PreloadFirstTasksCount = 5;
-            // For debugging, this allows us to multiply the number of cards for each task
-            public static final int TaskEntryMultiplier = 1;
         }
 
         public static class TaskStackView {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 928c732..e193a95 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -20,7 +20,6 @@
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -109,18 +108,20 @@
     Handler mLoadThreadHandler;
     Handler mMainThreadHandler;
 
+    SystemServicesProxy mSystemServicesProxy;
     TaskResourceLoadQueue mLoadQueue;
-    DrawableLruCache mIconCache;
+    DrawableLruCache mApplicationIconCache;
     BitmapLruCache mThumbnailCache;
 
     boolean mCancelled;
     boolean mWaitingOnLoadQueue;
 
     /** Constructor, creates a new loading thread that loads task resources in the background */
-    public TaskResourceLoader(TaskResourceLoadQueue loadQueue, DrawableLruCache iconCache,
+    public TaskResourceLoader(TaskResourceLoadQueue loadQueue,
+                              DrawableLruCache applicationIconCache,
                               BitmapLruCache thumbnailCache) {
         mLoadQueue = loadQueue;
-        mIconCache = iconCache;
+        mApplicationIconCache = applicationIconCache;
         mThumbnailCache = thumbnailCache;
         mMainThreadHandler = new Handler();
         mLoadThread = new HandlerThread("Recents-TaskResourceLoader");
@@ -135,6 +136,7 @@
         Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|start]");
         mContext = context;
         mCancelled = false;
+        mSystemServicesProxy = new SystemServicesProxy(context);
         // Notify the load thread to start loading
         synchronized(mLoadThread) {
             mLoadThread.notifyAll();
@@ -146,6 +148,7 @@
         Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|stop]");
         // Mark as cancelled for the thread to pick up
         mCancelled = true;
+        mSystemServicesProxy = null;
         // If we are waiting for the load queue for more tasks, then we can just reset the
         // Context now, since nothing is using it
         if (mWaitingOnLoadQueue) {
@@ -175,66 +178,60 @@
                     }
                 }
             } else {
+                SystemServicesProxy ssp = mSystemServicesProxy;
+
                 // Load the next item from the queue
                 Pair<Task, Boolean> nextTaskData = mLoadQueue.nextTask();
                 final Task t = nextTaskData.first;
                 final boolean forceLoadTask = nextTaskData.second;
                 if (t != null) {
-                    try {
-                        Drawable loadIcon = mIconCache.get(t.key);
-                        Bitmap loadThumbnail = mThumbnailCache.get(t.key);
-                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                "  [TaskResourceLoader|load]",
-                                t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
-                                        " forceLoad: " + forceLoadTask);
-                        // Load the icon
-                        if (loadIcon == null || forceLoadTask) {
-                            PackageManager pm = mContext.getPackageManager();
-                            ActivityInfo info = pm.getActivityInfo(t.key.baseIntent.getComponent(),
-                                    PackageManager.GET_META_DATA);
-                            Drawable icon = info.loadIcon(pm);
-                            if (!mCancelled) {
-                                if (icon != null) {
-                                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                            "    [TaskResourceLoader|loadIcon]",
-                                            icon);
-                                    loadIcon = icon;
-                                    mIconCache.put(t.key, icon);
-                                }
-                            }
-                        }
-                        // Load the thumbnail
-                        if (loadThumbnail == null || forceLoadTask) {
-                            ActivityManager am = (ActivityManager)
-                                    mContext.getSystemService(Context.ACTIVITY_SERVICE);
-                            Bitmap thumbnail = am.getTaskTopThumbnail(t.key.id);
-                            if (!mCancelled) {
-                                if (thumbnail != null) {
-                                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                            "    [TaskResourceLoader|loadThumbnail]",
-                                            thumbnail);
-                                    loadThumbnail = thumbnail;
-                                    mThumbnailCache.put(t.key, thumbnail);
-                                } else {
-                                    Console.logError(mContext,
-                                            "Failed to load task top thumbnail for: " +
-                                                    t.key.baseIntent.getComponent().getPackageName());
-                                }
-                            }
-                        }
+                    Drawable loadIcon = mApplicationIconCache.get(t.key);
+                    Bitmap loadThumbnail = mThumbnailCache.get(t.key);
+                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                            "  [TaskResourceLoader|load]",
+                            t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
+                                    " forceLoad: " + forceLoadTask);
+                    // Load the application icon
+                    if (loadIcon == null || forceLoadTask) {
+                        ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent());
+                        Drawable icon = ssp.getActivityIcon(info);
                         if (!mCancelled) {
-                            // Notify that the task data has changed
-                            final Drawable newIcon = loadIcon;
-                            final Bitmap newThumbnail = loadThumbnail;
-                            mMainThreadHandler.post(new Runnable() {
-                                @Override
-                                public void run() {
-                                    t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
-                                }
-                            });
+                            if (icon != null) {
+                                Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                                        "    [TaskResourceLoader|loadIcon]",
+                                        icon);
+                                loadIcon = icon;
+                                mApplicationIconCache.put(t.key, icon);
+                            }
                         }
-                    } catch (PackageManager.NameNotFoundException ne) {
-                        ne.printStackTrace();
+                    }
+                    // Load the thumbnail
+                    if (loadThumbnail == null || forceLoadTask) {
+                        Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id);
+                        if (!mCancelled) {
+                            if (thumbnail != null) {
+                                Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                                        "    [TaskResourceLoader|loadThumbnail]",
+                                        thumbnail);
+                                loadThumbnail = thumbnail;
+                                mThumbnailCache.put(t.key, thumbnail);
+                            } else {
+                                Console.logError(mContext,
+                                        "Failed to load task top thumbnail for: " +
+                                                t.key.baseIntent.getComponent().getPackageName());
+                            }
+                        }
+                    }
+                    if (!mCancelled) {
+                        // Notify that the task data has changed
+                        final Drawable newIcon = loadIcon;
+                        final Bitmap newThumbnail = loadThumbnail;
+                        mMainThreadHandler.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
+                            }
+                        });
                     }
                 }
 
@@ -296,7 +293,8 @@
 public class RecentsTaskLoader {
     static RecentsTaskLoader sInstance;
 
-    DrawableLruCache mIconCache;
+    SystemServicesProxy mSystemServicesProxy;
+    DrawableLruCache mApplicationIconCache;
     BitmapLruCache mThumbnailCache;
     TaskResourceLoadQueue mLoadQueue;
     TaskResourceLoader mLoader;
@@ -304,7 +302,7 @@
     int mMaxThumbnailCacheSize;
     int mMaxIconCacheSize;
 
-    BitmapDrawable mDefaultIcon;
+    BitmapDrawable mDefaultApplicationIcon;
     Bitmap mDefaultThumbnail;
 
     /** Private Constructor */
@@ -324,11 +322,12 @@
                 "[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
                 " iconCache: " + iconCacheSize);
 
-        // Initialize the cache and loaders
+        // Initialize the proxy, cache and loaders
+        mSystemServicesProxy = new SystemServicesProxy(context);
         mLoadQueue = new TaskResourceLoadQueue();
-        mIconCache = new DrawableLruCache(iconCacheSize);
+        mApplicationIconCache = new DrawableLruCache(iconCacheSize);
         mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
-        mLoader = new TaskResourceLoader(mLoadQueue, mIconCache, mThumbnailCache);
+        mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache);
 
         // Create the default assets
         Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
@@ -339,10 +338,10 @@
         c.setBitmap(mDefaultThumbnail);
         c.drawColor(0x00000000);
         c.setBitmap(null);
-        mDefaultIcon = new BitmapDrawable(context.getResources(), icon);
+        mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
         Console.log(Constants.DebugFlags.App.TaskDataLoader,
                 "[RecentsTaskLoader|defaultBitmaps]",
-                "icon: " + mDefaultIcon + " thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
+                "icon: " + mDefaultApplicationIcon + " thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
     }
 
     /** Initializes the recents task loader */
@@ -358,6 +357,11 @@
         return sInstance;
     }
 
+    /** Returns the system services proxy */
+    public SystemServicesProxy getSystemServicesProxy() {
+        return mSystemServicesProxy;
+    }
+
     /** Reload the set of recent tasks */
     SpaceNode reload(Context context, int preloadCount) {
         Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
@@ -367,142 +371,119 @@
         SpaceNode root = new SpaceNode(context);
         root.setStack(stack);
 
-        try {
-            long t1 = System.currentTimeMillis();
+        long t1 = System.currentTimeMillis();
 
-            PackageManager pm = context.getPackageManager();
-            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        // Get the recent tasks
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RecentTaskInfo> tasks =
+                ssp.getRecentTasks(25, UserHandle.CURRENT.getIdentifier());
+        Collections.reverse(tasks);
+        Console.log(Constants.DebugFlags.App.TimeSystemCalls,
+                "[RecentsTaskLoader|getRecentTasks]",
+                "" + (System.currentTimeMillis() - t1) + "ms");
+        Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                "[RecentsTaskLoader|tasks]", "" + tasks.size());
 
-            // Get the recent tasks
-            List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(25,
-                    ActivityManager.RECENT_IGNORE_UNAVAILABLE |
-                    ActivityManager.RECENT_INCLUDE_PROFILES, UserHandle.CURRENT.getIdentifier());
-            Collections.reverse(tasks);
-            Console.log(Constants.DebugFlags.App.TimeSystemCalls,
-                    "[RecentsTaskLoader|getRecentTasks]",
-                    "" + (System.currentTimeMillis() - t1) + "ms");
-            Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                    "[RecentsTaskLoader|tasks]", "" + tasks.size());
+        // Remove home/recents tasks
+        Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
+        while (iter.hasNext()) {
+            ActivityManager.RecentTaskInfo t = iter.next();
 
-            // Remove home/recents tasks
-            Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
-            while (iter.hasNext()) {
-                ActivityManager.RecentTaskInfo t = iter.next();
-
-                // Skip tasks in the home stack
-                if (am.isInHomeStack(t.persistentId)) {
-                    iter.remove();
-                    continue;
-                }
-                // Skip tasks from this Recents package
-                if (t.baseIntent.getComponent().getPackageName().equals(context.getPackageName())) {
-                    iter.remove();
-                    continue;
-                }
+            // Skip tasks in the home stack
+            if (ssp.isInHomeStack(t.persistentId)) {
+                iter.remove();
+                continue;
             }
-
-            // Add each task to the task stack
-            t1 = System.currentTimeMillis();
-            int taskCount = tasks.size();
-            for (int i = 0; i < taskCount; i++) {
-                ActivityManager.RecentTaskInfo t = tasks.get(i);
-                ActivityInfo info = pm.getActivityInfo(t.baseIntent.getComponent(),
-                        PackageManager.GET_META_DATA);
-                String title = info.loadLabel(pm).toString();
-                boolean isForemostTask = (i == (taskCount - 1));
-
-                // Preload the specified number of apps
-                if (i >= (taskCount - preloadCount)) {
-                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                            "[RecentsTaskLoader|preloadTask]",
-                            "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
-
-                    String label = (t.activityLabel == null ? title : t.activityLabel.toString());
-                    BitmapDrawable bd = null;
-                    if (t.activityIcon != null) {
-                        bd = new BitmapDrawable(res, t.activityIcon);
-                    }
-                    Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, label, bd);
-
-                    // Load the icon (if possible and not the foremost task, from the cache)
-                    if (task.icon != null) {
-                        mIconCache.put(task.key, task.icon);
-                    } else {
-                        if (!isForemostTask) {
-                            task.icon = mIconCache.get(task.key);
-                            if (task.icon != null) {
-                                // Even though we get things from the cache, we should update them
-                                // if they've changed in the bg
-                                tasksToForceLoad.add(task);
-                            }
-                        }
-                        if (task.icon == null) {
-                            task.icon = info.loadIcon(pm);
-                            if (task.icon != null) {
-                                mIconCache.put(task.key, task.icon);
-                            } else {
-                                task.icon = mDefaultIcon;
-                            }
-                        }
-                    }
-
-                    // Load the thumbnail (if possible and not the foremost task, from the cache)
-                    if (!isForemostTask) {
-                        task.thumbnail = mThumbnailCache.get(task.key);
-                        if (task.thumbnail != null) {
-                            // Even though we get things from the cache, we should update them if
-                            // they've changed in the bg
-                            tasksToForceLoad.add(task);
-                        }
-                    }
-                    if (task.thumbnail == null) {
-                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                "[RecentsTaskLoader|loadingTaskThumbnail]");
-                        task.thumbnail = am.getTaskTopThumbnail(t.id);
-                        if (task.thumbnail != null) {
-                            mThumbnailCache.put(task.key, task.thumbnail);
-                        } else {
-                            task.thumbnail = mDefaultThumbnail;
-                        }
-                    }
-
-                    // Create as many tasks a we want to multiply by
-                    for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
-                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
-                        stack.addTask(task);
-                    }
-                } else {
-                    // Create as many tasks a we want to multiply by
-                    for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
-                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
-                        stack.addTask(new Task(t.persistentId, (t.id > -1), t.baseIntent, title,
-                                null, null));
-                    }
-                }
+            // Skip tasks from this Recents package
+            if (t.baseIntent.getComponent().getPackageName().equals(context.getPackageName())) {
+                iter.remove();
+                continue;
             }
-            Console.log(Constants.DebugFlags.App.TimeSystemCalls,
-                    "[RecentsTaskLoader|getAllTaskTopThumbnail]",
-                    "" + (System.currentTimeMillis() - t1) + "ms");
-
-            /*
-            // Get all the stacks
-            t1 = System.currentTimeMillis();
-            List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
-            Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
-            Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
-            for (ActivityManager.StackInfo s : stackInfos) {
-                Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [RecentsTaskLoader|stack]", s.toString());
-                if (stacks.containsKey(s.stackId)) {
-                    stacks.get(s.stackId).setRect(s.bounds);
-                }
-            }
-            */
-        } catch (Exception e) {
-            e.printStackTrace();
         }
 
+        // Add each task to the task stack
+        t1 = System.currentTimeMillis();
+        int taskCount = tasks.size();
+        for (int i = 0; i < taskCount; i++) {
+            ActivityManager.RecentTaskInfo t = tasks.get(i);
+            ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent());
+            String activityLabel = (t.activityLabel == null ? ssp.getActivityLabel(info) :
+                    t.activityLabel.toString());
+            Bitmap activityIcon = t.activityIcon;
+            boolean isForemostTask = (i == (taskCount - 1));
+
+            // Create a new task
+            Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, activityLabel,
+                    activityIcon);
+
+            // Preload the specified number of apps
+            if (i >= (taskCount - preloadCount)) {
+                Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                        "[RecentsTaskLoader|preloadTask]",
+                        "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
+
+                // Load the icon (if possible and not the foremost task, from the cache)
+                if (!isForemostTask) {
+                    task.applicationIcon = mApplicationIconCache.get(task.key);
+                    if (task.applicationIcon != null) {
+                        // Even though we get things from the cache, we should update them
+                        // if they've changed in the bg
+                        tasksToForceLoad.add(task);
+                    }
+                }
+                if (task.applicationIcon == null) {
+                    task.applicationIcon = ssp.getActivityIcon(info);
+                    if (task.applicationIcon != null) {
+                        mApplicationIconCache.put(task.key, task.applicationIcon);
+                    } else {
+                        task.applicationIcon = mDefaultApplicationIcon;
+                    }
+                }
+
+                // Load the thumbnail (if possible and not the foremost task, from the cache)
+                if (!isForemostTask) {
+                    task.thumbnail = mThumbnailCache.get(task.key);
+                    if (task.thumbnail != null) {
+                        // Even though we get things from the cache, we should update them if
+                        // they've changed in the bg
+                        tasksToForceLoad.add(task);
+                    }
+                }
+                if (task.thumbnail == null) {
+                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                            "[RecentsTaskLoader|loadingTaskThumbnail]");
+                    task.thumbnail = ssp.getTaskThumbnail(task.key.id);
+                    if (task.thumbnail != null) {
+                        mThumbnailCache.put(task.key, task.thumbnail);
+                    } else {
+                        task.thumbnail = mDefaultThumbnail;
+                    }
+                }
+            }
+
+            // Add the task to the stack
+            Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
+            stack.addTask(task);
+        }
+        Console.log(Constants.DebugFlags.App.TimeSystemCalls,
+                "[RecentsTaskLoader|getAllTaskTopThumbnail]",
+                "" + (System.currentTimeMillis() - t1) + "ms");
+
+        /*
+        // Get all the stacks
+        t1 = System.currentTimeMillis();
+        List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
+        Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
+        Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
+        for (ActivityManager.StackInfo s : stackInfos) {
+            Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [RecentsTaskLoader|stack]", s.toString());
+            if (stacks.containsKey(s.stackId)) {
+                stacks.get(s.stackId).setRect(s.bounds);
+            }
+        }
+        */
+
         // Start the task loader
         mLoader.start(context);
 
@@ -516,16 +497,16 @@
 
     /** Acquires the task resource data from the pool. */
     public void loadTaskData(Task t) {
-        Drawable icon = mIconCache.get(t.key);
+        Drawable applicationIcon = mApplicationIconCache.get(t.key);
         Bitmap thumbnail = mThumbnailCache.get(t.key);
 
         Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
-                t + " icon: " + icon + " thumbnail: " + thumbnail +
+                t + " applicationIcon: " + applicationIcon + " thumbnail: " + thumbnail +
                         " thumbnailCacheSize: " + mThumbnailCache.size());
 
         boolean requiresLoad = false;
-        if (icon == null) {
-            icon = mDefaultIcon;
+        if (applicationIcon == null) {
+            applicationIcon = mDefaultApplicationIcon;
             requiresLoad = true;
         }
         if (thumbnail == null) {
@@ -535,7 +516,7 @@
         if (requiresLoad) {
             mLoadQueue.addTask(t, false);
         }
-        t.notifyTaskDataLoaded(thumbnail, icon, false);
+        t.notifyTaskDataLoaded(thumbnail, applicationIcon, false);
     }
 
     /** Releases the task resource data back into the pool. */
@@ -545,7 +526,7 @@
                 " thumbnailCacheSize: " + mThumbnailCache.size());
 
         mLoadQueue.removeTask(t);
-        t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultIcon);
+        t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
     }
 
     /** Completely removes the resource data from the pool. */
@@ -555,8 +536,8 @@
 
         mLoadQueue.removeTask(t);
         mThumbnailCache.remove(t.key);
-        mIconCache.remove(t.key);
-        t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultIcon);
+        mApplicationIconCache.remove(t.key);
+        t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
     }
 
     /** Stops the task loader and clears all pending tasks */
@@ -579,19 +560,19 @@
             case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
                 // We are leaving recents, so trim the data a bit
                 mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2);
-                mIconCache.trimToSize(mMaxIconCacheSize / 2);
+                mApplicationIconCache.trimToSize(mMaxIconCacheSize / 2);
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
             case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                 // We are going to be low on memory
                 mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4);
-                mIconCache.trimToSize(mMaxIconCacheSize / 4);
+                mApplicationIconCache.trimToSize(mMaxIconCacheSize / 4);
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
             case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                 // We are low on memory, so release everything
                 mThumbnailCache.evictAll();
-                mIconCache.evictAll();
+                mApplicationIconCache.evictAll();
                 break;
             default:
                 break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
new file mode 100644
index 0000000..f147fbc6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -0,0 +1,186 @@
+/*
+ * 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.recents;
+
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Acts as a shim around the real system services that we need to access data from, and provides
+ * a point of injection when testing UI.
+ */
+public class SystemServicesProxy {
+    ActivityManager mAm;
+    PackageManager mPm;
+    String mPackage;
+
+    Bitmap mDummyIcon;
+
+    /** Private constructor */
+    public SystemServicesProxy(Context context) {
+        mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        mPm = context.getPackageManager();
+        mPackage = context.getPackageName();
+
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            // Create a dummy icon
+            mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
+            Canvas c = new Canvas(mDummyIcon);
+            c.drawColor(0xFFFF0000);
+            c.setBitmap(null);
+        }
+    }
+
+    /** Returns a list of the recents tasks */
+    public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
+        if (mAm == null) return null;
+
+        // If we are mocking, then create some recent tasks
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            ArrayList<ActivityManager.RecentTaskInfo> tasks =
+                    new ArrayList<ActivityManager.RecentTaskInfo>();
+            int count = Math.min(numTasks, Constants.DebugFlags.App.SystemServicesProxyMockTaskCount);
+            for (int i = 0; i < count; i++) {
+                // Create a dummy component name
+                int packageIndex = i % Constants.DebugFlags.App.SystemServicesProxyMockPackageCount;
+                ComponentName cn = new ComponentName("com.android.test" + packageIndex,
+                        "com.android.test" + i + ".Activity");
+                // Create the recent task info
+                ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
+                rti.id = rti.persistentId = i;
+                rti.baseIntent = new Intent();
+                rti.baseIntent.setComponent(cn);
+                rti.description = rti.activityLabel =
+                        Long.toString(Math.abs(new Random().nextLong()), 36);
+                if (i % 2 == 0) {
+                    rti.activityIcon = Bitmap.createBitmap(mDummyIcon);
+                }
+                tasks.add(rti);
+            }
+            return tasks;
+        }
+
+        return mAm.getRecentTasksForUser(numTasks,
+                ActivityManager.RECENT_IGNORE_UNAVAILABLE |
+                ActivityManager.RECENT_INCLUDE_PROFILES, userId);
+    }
+
+    /** Returns a list of the running tasks */
+    public List<ActivityManager.RunningTaskInfo> getRunningTasks(int numTasks) {
+        if (mAm == null) return null;
+        return mAm.getRunningTasks(numTasks);
+    }
+
+    /** Returns whether the specified task is in the home stack */
+    public boolean isInHomeStack(int taskId) {
+        if (mAm == null) return false;
+
+        // If we are mocking, then just return false
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            return false;
+        }
+
+        return mAm.isInHomeStack(taskId);
+    }
+
+    /** Returns the top task thumbnail for the given task id */
+    public Bitmap getTaskThumbnail(int taskId) {
+        if (mAm == null) return null;
+
+        // If we are mocking, then just return a dummy thumbnail
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            Bitmap thumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+            Canvas c = new Canvas(thumbnail);
+            c.drawColor(0xFF00ff00);
+            c.setBitmap(null);
+            return thumbnail;
+        }
+
+        return mAm.getTaskTopThumbnail(taskId);
+    }
+
+    /** Moves a task to the front with the specified activity options */
+    public void moveTaskToFront(int taskId, ActivityOptions opts) {
+        if (mAm == null) return;
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
+
+        if (opts != null) {
+            mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME,
+                    opts.toBundle());
+        } else {
+            mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME);
+        }
+    }
+
+    /** Removes the task and kills the process */
+    public void removeTask(int taskId) {
+        if (mAm == null) return;
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
+
+        mAm.removeTask(taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+    }
+
+    /** Returns the activity info for a given component name */
+    public ActivityInfo getActivityInfo(ComponentName cn) {
+        if (mPm == null) return null;
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
+
+        try {
+            return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
+        } catch (PackageManager.NameNotFoundException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /** Returns the activity label */
+    public String getActivityLabel(ActivityInfo info) {
+        if (mPm == null) return null;
+
+        // If we are mocking, then return a mock label
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            return "Recent Task";
+        }
+
+        return info.loadLabel(mPm).toString();
+    }
+
+    /** Returns the activity icon */
+    public Drawable getActivityIcon(ActivityInfo info) {
+        if (mPm == null) return null;
+
+        // If we are mocking, then return a mock label
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            return new ColorDrawable(0xFFff0000);
+        }
+
+        return info.loadIcon(mPm);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 677334d..ed2ab2a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -19,7 +19,6 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
-import com.android.systemui.recents.Constants;
 
 
 /**
@@ -61,23 +60,19 @@
     }
 
     public TaskKey key;
-    public String title;
-    public Drawable icon;
+    public Drawable applicationIcon;
+    public String activityLabel;
+    public Bitmap activityIcon;
     public Bitmap thumbnail;
     public boolean isActive;
 
     TaskCallbacks mCb;
 
-    public Task(int id, boolean isActive, Intent intent, String activityTitle, Drawable icon) {
-        this(id, isActive, intent, activityTitle, icon, null);
-    }
-
-    public Task(int id, boolean isActive, Intent intent, String activityTitle, Drawable icon,
-                Bitmap thumbnail) {
+    public Task(int id, boolean isActive, Intent intent, String activityTitle,
+                Bitmap activityIcon) {
         this.key = new TaskKey(id, intent);
-        this.title = activityTitle;
-        this.icon = icon;
-        this.thumbnail = thumbnail;
+        this.activityLabel = activityTitle;
+        this.activityIcon = activityIcon;
         this.isActive = isActive;
     }
 
@@ -87,8 +82,9 @@
     }
 
     /** Notifies the callback listeners that this task has been loaded */
-    public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable icon, boolean reloadingTaskData) {
-        this.icon = icon;
+    public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable applicationIcon,
+                                     boolean reloadingTaskData) {
+        this.applicationIcon = applicationIcon;
         this.thumbnail = thumbnail;
         if (mCb != null) {
             mCb.onTaskDataLoaded(reloadingTaskData);
@@ -96,8 +92,8 @@
     }
 
     /** Notifies the callback listeners that this task has been unloaded */
-    public void notifyTaskDataUnloaded(Bitmap defaultThumbnail, Drawable defaultIcon) {
-        icon = defaultIcon;
+    public void notifyTaskDataUnloaded(Bitmap defaultThumbnail, Drawable defaultApplicationIcon) {
+        applicationIcon = defaultApplicationIcon;
         thumbnail = defaultThumbnail;
         if (mCb != null) {
             mCb.onTaskDataUnloaded();
@@ -106,14 +102,7 @@
 
     @Override
     public boolean equals(Object o) {
-        // If we have multiple task entries for the same task, then we do the simple object
-        // equality check
-        if (Constants.Values.RecentsTaskLoader.TaskEntryMultiplier > 1) {
-            return super.equals(o);
-        }
-
-        // Otherwise, check that the id and intent match (the other fields can be asynchronously
-        // loaded and is unsuitable to testing the identity of this Task)
+        // Check that the id matches
         Task t = (Task) o;
         return key.equals(t.key);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index e89bde5..cb52794 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.recents.views;
 
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
@@ -30,6 +29,7 @@
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsTaskLoader;
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
@@ -246,14 +246,8 @@
 
                 if (task.isActive) {
                     // Bring an active task to the foreground
-                    ActivityManager am = (ActivityManager)
-                            stackView.getContext().getSystemService(Context.ACTIVITY_SERVICE);
-                    if (opts != null) {
-                        am.moveTaskToFront(task.key.id, ActivityManager.MOVE_TASK_WITH_HOME,
-                                opts.toBundle());
-                    } else {
-                        am.moveTaskToFront(task.key.id, ActivityManager.MOVE_TASK_WITH_HOME);
-                    }
+                    RecentsTaskLoader.getInstance().getSystemServicesProxy()
+                            .moveTaskToFront(task.key.id, opts);
                 } else {
                     // Launch the activity with the desired animation
                     Intent i = new Intent(task.key.baseIntent);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index 235c6cc..c9a6d67 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -17,21 +17,12 @@
 package com.android.systemui.recents.views;
 
 import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Typeface;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.animation.AccelerateDecelerateInterpolator;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
 import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.model.Task;
 
 
@@ -39,6 +30,7 @@
 class TaskBarView extends FrameLayout {
     Task mTask;
 
+    ImageView mApplicationIcon;
     ImageView mActivityIcon;
     TextView mActivityDescription;
 
@@ -61,6 +53,7 @@
     @Override
     protected void onFinishInflate() {
         // Initialize the icon and description views
+        mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
         mActivityIcon = (ImageView) findViewById(R.id.activity_icon);
         mActivityDescription = (TextView) findViewById(R.id.activity_description);
     }
@@ -68,9 +61,13 @@
     /** Binds the bar view to the task */
     void rebindToTask(Task t, boolean animate) {
         mTask = t;
-        if (t.icon != null) {
-            mActivityIcon.setImageDrawable(t.icon);
-            mActivityDescription.setText(t.title);
+        if (t.applicationIcon != null) {
+            mApplicationIcon.setImageDrawable(t.applicationIcon);
+            mActivityDescription.setText(t.activityLabel);
+            if (t.activityIcon != null) {
+                mActivityIcon.setImageBitmap(t.activityIcon);
+                mActivityIcon.setVisibility(View.VISIBLE);
+            }
             if (animate) {
                 // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
             }
@@ -80,7 +77,9 @@
     /** Unbinds the bar view from the task */
     void unbindFromTask() {
         mTask = null;
-        mActivityIcon.setImageDrawable(null);
+        mApplicationIcon.setImageDrawable(null);
+        mActivityIcon.setImageBitmap(null);
+        mActivityIcon.setVisibility(View.INVISIBLE);
         mActivityDescription.setText("");
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index aeb571d..dfd608c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -22,7 +22,6 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -40,6 +39,7 @@
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.RecentsTaskLoader;
+import com.android.systemui.recents.SystemServicesProxy;
 import com.android.systemui.recents.Utilities;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
@@ -234,7 +234,8 @@
                         // When we are picking up a new view from the view pool, prepare it for any
                         // following animation by putting it in a reasonable place
                         if (mStackViewsAnimationDuration > 0 && i != 0) {
-                            int fromIndex = (transform.t < 0) ? (i - 1) : (i + 1);
+                            int fromIndex = (transform.t < 0) ? (visibleRange[0] - 1) :
+                                    (visibleRange[1] + 1);
                             tv.updateViewPropertiesToTaskTransform(null,
                                     getStackTransform(fromIndex, stackScroll), 0);
                         }
@@ -1268,12 +1269,7 @@
         loader.deleteTaskData(task);
 
         // Remove the task from activity manager
-        final ActivityManager am = (ActivityManager)
-                activity.getSystemService(Context.ACTIVITY_SERVICE);
-        if (am != null) {
-            am.removeTask(tv.getTask().key.id,
-                    ActivityManager.REMOVE_TASK_KILL_PROCESS);
-        }
+        RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(tv.getTask().key.id);
 
         // If there are no remaining tasks, then either unfilter the current stack, or just close
         // the activity if there are no filtered stacks
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index e04a1b2..2c27d44 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -75,7 +75,7 @@
         // Bind the views
         mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
         mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
-        mBarView.mActivityIcon.setOnClickListener(this);
+        mBarView.mApplicationIcon.setOnClickListener(this);
         if (mTaskDataLoaded) {
             onTaskDataLoaded(false);
         }
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 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.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.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 @@
     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 @@
 
     // all notifications
     protected NotificationData mNotificationData = new NotificationData();
-    protected ViewGroup mPile;
+    protected NotificationStackScrollLayout mStackScroller;
 
     protected NotificationData.Entry mInterruptingNotificationEntry;
     protected long mInterruptingNotificationTime;
@@ -1033,7 +1031,7 @@
         }
         // 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 @@
         return super.dispatchPopulateAccessibilityEvent(event);
     }
 
-    // We draw the handle ourselves so that it's always glued to the bottom of the window.
-    @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);
-        }
-    }
-
-    @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);
+    /**
+     * 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
     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());
-            }
+        // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
+        // implementation.
+        return super.onTouchEvent(event);
+    }
+
+    @Override
+    protected boolean isScrolledToBottom() {
+        if (!isInSettings()) {
+            return mNotificationStackScroller.isScrolledToBottom();
         }
-        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.isScrolledToBottom();
+    }
+
+    @Override
+    protected int getMaxPanelHeight() {
+        if (!isInSettings()) {
+            int maxPanelHeight = super.getMaxPanelHeight();
+            int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
+            return maxPanelHeight - emptyBottomMargin;
         }
-        return mHandleView.dispatchTouchEvent(event);
+        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)));
+        }
+    }
+
+    @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.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 @@
 
     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 @@
     private boolean mRubberbanding;
     private boolean mTracking;
     private int mTrackingPointer;
+    private int mTouchSlop;
 
     private TimeAnimator mTimeAnimator;
     private ObjectAnimator mPeekAnimator;
@@ -198,7 +200,6 @@
         }
     }
 
-    private int[] mAbsPos = new int[2];
     PanelBar mBar;
 
     private final TimeListener mAnimationCallback = new TimeListener() {
@@ -220,7 +221,7 @@
     };
 
     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 @@
             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 @@
             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 @@
         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 @@
         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 @@
         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 @@
 
         // 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 @@
 
     @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 @@
             h = 0;
         }
 
-        float fh = getFullHeight();
+        float fh = getMaxPanelHeight();
         if (fh == 0) {
             // Hmm, full height hasn't been computed yet
         }
@@ -593,9 +691,13 @@
 
         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");
+        }
 
-        requestLayout();
+        onHeightUpdated(mExpandedHeight);
+
 //        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
 //        lp.height = (int) mExpandedHeight;
 //        setLayoutParams(lp);
@@ -603,13 +705,23 @@
         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 @@
             }
             frac = 0;
         }
-        setExpandedHeight(getFullHeight() * frac);
+        setExpandedHeight(getMaxPanelHeight() * frac);
     }
 
     public float getExpandedHeight() {
@@ -633,7 +745,7 @@
     }
 
     public boolean isFullyExpanded() {
-        return mExpandedHeight >= getFullHeight();
+        return mExpandedHeight >= getMaxPanelHeight();
     }
 
     public boolean isFullyCollapsed() {
@@ -681,12 +793,12 @@
     }
 
     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.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.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 @@
     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 @@
 
     // 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 @@
             }
         }};
 
+    private Runnable mOnFlipRunnable;
+
+    public void setOnFlipRunnable(Runnable onFlipRunnable) {
+        mOnFlipRunnable = onFlipRunnable;
+    }
+
     @Override
     public void setZenMode(int mode) {
         super.setZenMode(mode);
@@ -417,7 +419,8 @@
         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 @@
             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 @@
         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);
+        mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
+                R.id.notification_stack_scroller);
+        mStackScroller.setLongPressListener(getNotificationLongClicker());
 
-            // 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);
-
-
+        mExpandedContents = mStackScroller;
 
         mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
 
@@ -551,7 +533,8 @@
             }
         }
         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 @@
         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 @@
             }
 
             // 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 @@
     }
 
     private void loadNotificationShade() {
-        if (mPile == null) return;
+        if (mStackScroller == null) return;
 
         int N = mNotificationData.size();
 
@@ -1092,21 +1075,21 @@
         }
 
         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 @@
         // 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 @@
         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 @@
         }
 
         mExpandedVisible = true;
-        if (!ENABLE_NOTIFICATION_STACK) {
-            ((NotificationRowLayout) mPile).setLayoutTransitionsEnabled(true);
-        }
         if (mNavigationBarView != null)
             mNavigationBarView.setSlippery(true);
 
@@ -1600,7 +1582,7 @@
         }
 
         mNotificationPanel.expand();
-        if (mHasFlipSettings && mNotificationScroller.getVisibility() != View.VISIBLE) {
+        if (mHasFlipSettings && mStackScroller.getVisibility() != View.VISIBLE) {
             flipToNotifications();
         }
 
@@ -1614,11 +1596,11 @@
         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 @@
                 updateCarrierLabelVisibility(false);
             }
         }, FLIP_DURATION - 150);
+        if (mOnFlipRunnable != null) {
+            mOnFlipRunnable.run();
+        }
     }
 
     @Override
@@ -1676,11 +1661,21 @@
         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 @@
         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 @@
                 updateCarrierLabelVisibility(false);
             }
         }, FLIP_DURATION - 150);
+        if (mOnFlipRunnable != null) {
+            mOnFlipRunnable.run();
+        }
     }
 
     public void flipPanels() {
@@ -1766,8 +1764,8 @@
             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 @@
         }
 
         mExpandedVisible = false;
-        if (!ENABLE_NOTIFICATION_STACK) {
-            ((NotificationRowLayout) mPile).setLayoutTransitionsEnabled(false);
-        }
         if (mNavigationBarView != null)
             mNavigationBarView.setSlippery(false);
         visibilityChanged(false);
@@ -1806,53 +1801,6 @@
         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 @@
             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 @@
 
         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 @@
 
     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 @@
                             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.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 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 @@
     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 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 @@
         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.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 @@
     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 @@
      * 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 @@
     }
 
     /**
-     * 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 @@
         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 @@
         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 @@
         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 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         boolean scrollerWantsIt = false;
-        if (mAllowScrolling) {
+        if (!mSwipingInProgress) {
             scrollerWantsIt = onScrollTouch(ev);
         }
         boolean horizontalSwipeWantsIt = false;
@@ -409,12 +421,6 @@
                 }
                 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 @@
                 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 @@
         if (getChildCount() > 0) {
             int contentHeight = getContentHeight();
             scrollRange = Math.max(0,
-                    contentHeight - mMaxLayoutHeight + mCollapsedSize);
+                    contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
         }
         return scrollRange;
     }
@@ -697,7 +699,7 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         boolean scrollWantsIt = false;
-        if (mAllowScrolling) {
+        if (!mSwipingInProgress) {
             scrollWantsIt = onInterceptTouchEventScroll(ev);
         }
         boolean swipeWantsIt = false;
@@ -763,10 +765,6 @@
                     mLastMotionY = y;
                     initVelocityTrackerIfNotExists();
                     mVelocityTracker.addMovement(ev);
-                    final ViewParent parent = getParent();
-                    if (parent != null) {
-                        parent.requestDisallowInterceptTouchEvent(true);
-                    }
                 }
                 break;
             }
@@ -823,6 +821,7 @@
     private void setIsBeingDragged(boolean isDragged) {
         mIsBeingDragged = isDragged;
         if (isDragged) {
+            requestDisallowInterceptTouchEvent(true);
             mSwipeHelper.removeLongPressCallback();
         }
     }
@@ -841,10 +840,19 @@
     }
 
     @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 @@
         // 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 @@
         // 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 @@
                 // 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 @@
             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 @@
             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/MountService.java b/services/core/java/com/android/server/MountService.java
index c1d9fbd..b6e761c 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -158,6 +158,7 @@
         public static final int VolumeListResult               = 110;
         public static final int AsecListResult                 = 111;
         public static final int StorageUsersListResult         = 112;
+        public static final int CryptfsGetfieldResult          = 113;
 
         /*
          * 200 series - Requestion action has been successfully completed.
@@ -2251,6 +2252,49 @@
         }
     }
 
+    /**
+     * Set a field in the crypto header.
+     * @param field field to set
+     * @param contents contents to set in field
+     */
+    @Override
+    public void setField(String field, String contents) throws RemoteException {
+
+        waitForReady();
+
+        final NativeDaemonEvent event;
+        try {
+            event = mConnector.execute("cryptfs", "setfield", field, contents);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    /**
+     * Gets a field from the crypto header.
+     * @param field field to get
+     * @return contents of field
+     */
+    @Override
+    public String getField(String field) throws RemoteException {
+
+        waitForReady();
+
+        final NativeDaemonEvent event;
+        try {
+            final String[] contents = NativeDaemonEvent.filterMessageList(
+                    mConnector.executeForList("cryptfs", "getfield", field),
+                    VoldResponseCode.CryptfsGetfieldResult);
+            String result = new String();
+            for (String content : contents) {
+                result += content;
+            }
+            return result;
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
     @Override
     public String getPassword() throws RemoteException {
         if (!isReady()) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ac6f684..e9be1d7d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1019,7 +1019,7 @@
     final ActivityThread mSystemThread;
 
     int mCurrentUserId = 0;
-    int[] mCurrentProfileIds = new int[0]; // Accessed by ActivityStack
+    int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; // Accessed by ActivityStack
     private UserManagerService mUserManager;
 
     private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -6899,18 +6899,27 @@
                     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 @@
     }
 
     @Override
-    public void setRecentsLabel(IBinder token, CharSequence recentsLabel) {
+    public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
+            Bitmap activityIcon) {
         synchronized (this) {
             ActivityRecord r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
-                r.recentsLabel = recentsLabel.toString();
-            }
-        }
-    }
-
-    @Override
-    public void setRecentsIcon(IBinder token, Bitmap recentsIcon) {
-        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 @@
     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/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d949ba0..b894724 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -344,6 +344,7 @@
      * Checks whether the userid is a profile of the current user.
      */
     private boolean isCurrentProfileLocked(int userId) {
+        if (userId == mCurrentUser) return true;
         for (int i = 0; i < mService.mCurrentProfileIds.length; i++) {
             if (mService.mCurrentProfileIds[i] == userId) return true;
         }
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.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 @@
  *
  * <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,19 +53,38 @@
     // 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;
     }
 
     /**
+     * Called right after the class is instantiated. This method can be used to
+     * implement any initialization tasks for the instance.
+     */
+    abstract public void initialize();
+
+    /**
      * Return the binder token that identifies this instance.
      */
     public Binder getToken() {
@@ -69,6 +92,13 @@
     }
 
     /**
+     * Return the service instance.
+     */
+    public HdmiCecService getService() {
+        return mService;
+    }
+
+    /**
      * Return the type of this device.
      */
     public int getType() {
@@ -76,24 +106,6 @@
     }
 
     /**
-     * Set the name of the device. The name will be transferred via the message
-     * &lt;Set OSD Name&gt; to other HDMI-CEC devices connected through HDMI
-     * cables and shown on TV screen to identify the devicie.
-     *
-     * @param name name of the device
-     */
-    public void setName(String name) {
-        mName = name;
-    }
-
-    /**
-     * Return the name of this device.
-     */
-    public String getName() {
-        return mName;
-    }
-
-    /**
      * Register a listener to be invoked when events occur.
      *
      * @param listener the listern that will run
@@ -128,6 +140,7 @@
         if (opcode == HdmiCec.MESSAGE_ACTIVE_SOURCE) {
             mIsActiveSource = false;
         }
+
         if (mListeners.size() == 0) {
             return;
         }
@@ -167,4 +180,13 @@
     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.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.SparseArray;
 
 import com.android.server.SystemService;
+import libcore.util.EmptyArray;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -37,8 +39,6 @@
 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 @@
 
     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 @@
     @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 @@
         //       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 @@
                             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 @@
     }
 
     /**
-     * Called by native when a request for the device OSD name was received.
-     * The native part uses the return value to generate the message
-     * &lt;Set Osd Name&gt; 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
      * &lt;Set Menu Language&gt; in response. The language should be of
@@ -174,8 +163,7 @@
         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 @@
         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 @@
                         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 @@
         }
 
         @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 @@
         }
 
         @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 @@
     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 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 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..ff90cae 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9201,7 +9201,7 @@
         }
         
         // Successfully disabled the old package. Now proceed with re-installation
-        mLastScanError = PackageManager.INSTALL_SUCCEEDED;
+        res.returnCode = mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
         newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
         if (newPackage == null) {
@@ -9214,9 +9214,20 @@
                 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;
+                }
             }
-            updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
-            updatedSettings = true;
+
+            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+                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 @@
         @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/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2e5b8de..b12ae4f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -86,6 +86,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
@@ -311,7 +312,7 @@
      * Users that are profiles of the current user. These are also allowed to show windows
      * on the current user.
      */
-    int[] mCurrentProfileIds = new int[0];
+    int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER};
 
     final Context mContext;
 
@@ -5255,6 +5256,7 @@
 
     /* Called by WindowState */
     boolean isCurrentProfileLocked(int userId) {
+        if (userId == mCurrentUserId) return true;
         for (int i = 0; i < mCurrentProfileIds.length; i++) {
             if (mCurrentProfileIds[i] == userId) return true;
         }
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 @@
     jmethodID handleMessage;
     jmethodID handleHotplug;
     jmethodID getActiveSource;
-    jmethodID getOsdName;
     jmethodID getLanguage;
 } gHdmiCecServiceClassInfo;
 
@@ -84,6 +83,7 @@
     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 @@
 
     std::deque<MessageEntry> mMessageQueue;
     uint16_t mPhysicalAddress;
+    std::string mOsdName;
 };
 
 
@@ -373,6 +374,10 @@
     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::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 @@
             "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 @@
     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 @@
             (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 @@
     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
similarity index 94%
rename from tests/DynamicDrawableTest/Android.mk
rename to tests/VectorDrawableTest/Android.mk
index 5c51301..dd8a4d4 100644
--- a/tests/DynamicDrawableTest/Android.mk
+++ b/tests/VectorDrawableTest/Android.mk
@@ -19,7 +19,7 @@
 
 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
similarity index 99%
rename from tests/DynamicDrawableTest/AndroidManifest.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable-hdpi/icon.png
rename to tests/VectorDrawableTest/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/tests/DynamicDrawableTest/res/drawable/icon.png b/tests/VectorDrawableTest/res/drawable/icon.png
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/icon.png
rename to tests/VectorDrawableTest/res/drawable/icon.png
Binary files differ
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
similarity index 97%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml
rename to 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
similarity index 98%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_test01.xml
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_test02.xml
rename to tests/VectorDrawableTest/res/drawable/vector_test02.xml
diff --git a/tests/DynamicDrawableTest/res/values/strings.xml b/tests/VectorDrawableTest/res/values/strings.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/values/strings.xml
rename to tests/VectorDrawableTest/res/values/strings.xml
diff --git a/tests/DynamicDrawableTest/res/values/styles.xml b/tests/VectorDrawableTest/res/values/styles.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/values/styles.xml
rename to 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
similarity index 98%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
rename to 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 @@
             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
similarity index 98%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
rename to 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 @@
             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
similarity index 100%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
rename to 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
similarity index 98%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
rename to 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 @@
         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
similarity index 100%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
rename to 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
similarity index 100%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
rename to tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java