Merge "Add android.software.managedprofiles feature flag."
diff --git a/api/current.txt b/api/current.txt
index e0d392b..6417fac 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);
@@ -12084,11 +12088,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/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index f415c85..5454b46 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1033,18 +1033,18 @@
 
     public void runCreateUser() {
         String name;
-        int relatedUserId = -1;
+        int userId = -1;
         int flags = 0;
         String opt;
         while ((opt = nextOption()) != null) {
-            if ("--relatedTo".equals(opt)) {
+            if ("--profileOf".equals(opt)) {
                 String optionData = nextOptionData();
                 if (optionData == null || !isNumber(optionData)) {
                     System.err.println("Error: no USER_ID specified");
                     showUsage();
                     return;
                 } else {
-                    relatedUserId = Integer.parseInt(optionData);
+                    userId = Integer.parseInt(optionData);
                 }
             } else if ("--managed".equals(opt)) {
                 flags |= UserInfo.FLAG_MANAGED_PROFILE;
@@ -1062,14 +1062,14 @@
         name = arg;
         try {
             UserInfo info = null;
-            if (relatedUserId < 0) {
+            if (userId < 0) {
                 info = mUm.createUser(name, flags);
             } else {
                 if (Process.myUid() != 0) {
                     System.err.println("Error: not running as root.");
                     return;
                 }
-                info = mUm.createRelatedUser(name, flags, relatedUserId);
+                info = mUm.createProfileForUser(name, flags, userId);
             }
             if (info != null) {
                 System.out.println("Success: created user id " + info.id);
diff --git a/core/java/android/alsa/AlsaCardsParser.java b/core/java/android/alsa/AlsaCardsParser.java
new file mode 100644
index 0000000..f9af979
--- /dev/null
+++ b/core/java/android/alsa/AlsaCardsParser.java
@@ -0,0 +1,116 @@
+/*
+ * 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.alsascan;
+
+import android.util.Slog;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * @hide Retrieves information from an ALSA "cards" file.
+ */
+public class AlsaCardsParser {
+    private static final String TAG = "AlsaCardsParser";
+
+    private static LineTokenizer tokenizer_ = new LineTokenizer(" :[]");
+
+    public class AlsaCardRecord {
+        public int mCardNum = -1;
+        public String mField1 = "";
+        public String mCardName = "";
+        public String mCardDescription = "";
+
+        public AlsaCardRecord() {}
+
+        public boolean parse(String line, int lineIndex) {
+            int tokenIndex = 0;
+            int delimIndex = 0;
+            if (lineIndex == 0) {
+                // line # (skip)
+                tokenIndex = tokenizer_.nextToken(line, tokenIndex);
+                delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
+
+                // mField1
+                tokenIndex = tokenizer_.nextToken(line, delimIndex);
+                delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
+                mField1 = line.substring(tokenIndex, delimIndex);
+
+                // mCardName
+                tokenIndex = tokenizer_.nextToken(line, delimIndex);
+                // delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
+                mCardName = line.substring(tokenIndex);
+                // done
+              } else if (lineIndex == 1) {
+                  tokenIndex = tokenizer_.nextToken(line, 0);
+                  if (tokenIndex != -1) {
+                      mCardDescription = line.substring(tokenIndex);
+                  }
+            }
+
+            return true;
+        }
+
+        public String textFormat() {
+          return mCardName + " : " + mCardDescription;
+        }
+    }
+
+    private Vector<AlsaCardRecord> cardRecords_ = new Vector<AlsaCardRecord>();
+
+    public void scan() {
+          cardRecords_.clear();
+          final String cardsFilePath = "/proc/asound/cards";
+          File cardsFile = new File(cardsFilePath);
+          try {
+              FileReader reader = new FileReader(cardsFile);
+              BufferedReader bufferedReader = new BufferedReader(reader);
+              String line = "";
+              while ((line = bufferedReader.readLine()) != null) {
+                  AlsaCardRecord cardRecord = new AlsaCardRecord();
+                  cardRecord.parse(line, 0);
+                  cardRecord.parse(line = bufferedReader.readLine(), 1);
+                  cardRecords_.add(cardRecord);
+              }
+              reader.close();
+          } catch (FileNotFoundException e) {
+              e.printStackTrace();
+          } catch (IOException e) {
+              e.printStackTrace();
+          }
+      }
+
+      public AlsaCardRecord getCardRecordAt(int index) {
+          return cardRecords_.get(index);
+      }
+
+      public int getNumCardRecords() {
+          return cardRecords_.size();
+      }
+
+    public void Log() {
+      int numCardRecs = getNumCardRecords();
+      for (int index = 0; index < numCardRecs; ++index) {
+          Slog.w(TAG, "usb:" + getCardRecordAt(index).textFormat());
+      }
+    }
+
+    public AlsaCardsParser() {}
+}
diff --git a/core/java/android/alsa/AlsaDevicesParser.java b/core/java/android/alsa/AlsaDevicesParser.java
new file mode 100644
index 0000000..3835942
--- /dev/null
+++ b/core/java/android/alsa/AlsaDevicesParser.java
@@ -0,0 +1,240 @@
+/*
+ * 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.alsascan;
+
+import android.util.Slog;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * @hide
+ * Retrieves information from an ALSA "devices" file.
+ */
+public class AlsaDevicesParser {
+    private static final String TAG = "AlsaDevicesParser";
+
+    private static final int kIndex_CardDeviceField = 5;
+    private static final int kStartIndex_CardNum = 6;
+    private static final int kEndIndex_CardNum = 8; // one past
+    private static final int kStartIndex_DeviceNum = 9;
+    private static final int kEndIndex_DeviceNum = 11; // one past
+    private static final int kStartIndex_Type = 14;
+
+    private static LineTokenizer mTokenizer = new LineTokenizer(" :[]-");
+
+    private boolean mHasCaptureDevices = false;
+    private boolean mHasPlaybackDevices = false;
+    private boolean mHasMIDIDevices = false;
+
+    public class AlsaDeviceRecord {
+        public static final int kDeviceType_Unknown = -1;
+        public static final int kDeviceType_Audio = 0;
+        public static final int kDeviceType_Control = 1;
+        public static final int kDeviceType_MIDI = 2;
+
+        public static final int kDeviceDir_Unknown = -1;
+        public static final int kDeviceDir_Capture = 0;
+        public static final int kDeviceDir_Playback = 1;
+
+        int mCardNum = -1;
+        int mDeviceNum = -1;
+        int mDeviceType = kDeviceType_Unknown;
+        int mDeviceDir = kDeviceDir_Unknown;
+
+        public AlsaDeviceRecord() {
+        }
+
+        public boolean parse(String line) {
+            // "0123456789012345678901234567890"
+            // "  2: [ 0-31]: digital audio playback"
+            // "  3: [ 0-30]: digital audio capture"
+            // " 35: [ 1]   : control"
+            // " 36: [ 2- 0]: raw midi"
+
+            final int kToken_LineNum = 0;
+            final int kToken_CardNum = 1;
+            final int kToken_DeviceNum = 2;
+            final int kToken_Type0 = 3; // "digital", "control", "raw"
+            final int kToken_Type1 = 4; // "audio", "midi"
+            final int kToken_Type2 = 5; // "capture", "playback"
+
+            int tokenOffset = 0;
+            int delimOffset = 0;
+            int tokenIndex = kToken_LineNum;
+            while (true) {
+                tokenOffset = mTokenizer.nextToken(line, delimOffset);
+                if (tokenOffset == LineTokenizer.kTokenNotFound) {
+                    break; // bail
+                }
+                delimOffset = mTokenizer.nextDelimiter(line, tokenOffset);
+                if (delimOffset == LineTokenizer.kTokenNotFound) {
+                    delimOffset = line.length();
+                }
+                String token = line.substring(tokenOffset, delimOffset);
+
+                switch (tokenIndex) {
+                case kToken_LineNum:
+                    // ignore
+                    break;
+
+                case kToken_CardNum:
+                    mCardNum = Integer.parseInt(token);
+                    if (line.charAt(delimOffset) != '-') {
+                        tokenIndex++; // no device # in the token stream
+                    }
+                    break;
+
+                case kToken_DeviceNum:
+                    mDeviceNum = Integer.parseInt(token);
+                    break;
+
+                case kToken_Type0:
+                    if (token.equals("digital")) {
+                        // NOP
+                    } else if (token.equals("control")) {
+                        mDeviceType = kDeviceType_Control;
+                    } else if (token.equals("raw")) {
+                        // NOP
+                    }
+                    break;
+
+                case kToken_Type1:
+                    if (token.equals("audio")) {
+                        mDeviceType = kDeviceType_Audio;
+                    } else if (token.equals("midi")) {
+                        mDeviceType = kDeviceType_MIDI;
+                        mHasMIDIDevices = true;
+                    }
+                    break;
+
+                case kToken_Type2:
+                    if (token.equals("capture")) {
+                        mDeviceDir = kDeviceDir_Capture;
+                        mHasCaptureDevices = true;
+                    } else if (token.equals("playback")) {
+                        mDeviceDir = kDeviceDir_Playback;
+                        mHasPlaybackDevices = true;
+                    }
+                    break;
+                } // switch (tokenIndex)
+
+                tokenIndex++;
+            } // while (true)
+
+            return true;
+        } // parse()
+
+        public String textFormat() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("[" + mCardNum + ":" + mDeviceNum + "]");
+
+            switch (mDeviceType) {
+            case kDeviceType_Unknown:
+                sb.append(" N/A");
+                break;
+            case kDeviceType_Audio:
+                sb.append(" Audio");
+                break;
+            case kDeviceType_Control:
+                sb.append(" Control");
+                break;
+            case kDeviceType_MIDI:
+                sb.append(" MIDI");
+                break;
+            }
+
+            switch (mDeviceDir) {
+            case kDeviceDir_Unknown:
+                sb.append(" N/A");
+                break;
+            case kDeviceDir_Capture:
+                sb.append(" Capture");
+                break;
+            case kDeviceDir_Playback:
+                sb.append(" Playback");
+                break;
+            }
+
+            return sb.toString();
+        }
+    }
+
+    private Vector<AlsaDeviceRecord>
+            deviceRecords_ = new Vector<AlsaDeviceRecord>();
+
+    private boolean isLineDeviceRecord(String line) {
+        return line.charAt(kIndex_CardDeviceField) == '[';
+    }
+
+    public AlsaDevicesParser() {
+    }
+
+    public int getNumDeviceRecords() {
+        return deviceRecords_.size();
+    }
+
+    public AlsaDeviceRecord getDeviceRecordAt(int index) {
+        return deviceRecords_.get(index);
+    }
+
+    public void Log() {
+        int numDevRecs = getNumDeviceRecords();
+        for (int index = 0; index < numDevRecs; ++index) {
+            Slog.w(TAG, "usb:" + getDeviceRecordAt(index).textFormat());
+        }
+    }
+
+    public boolean hasPlaybackDevices() {
+        return mHasPlaybackDevices;
+    }
+
+    public boolean hasCaptureDevices() {
+        return mHasCaptureDevices;
+    }
+
+    public boolean hasMIDIDevices() {
+        return mHasMIDIDevices;
+    }
+
+    public void scan() {
+        deviceRecords_.clear();
+
+        final String devicesFilePath = "/proc/asound/devices";
+        File devicesFile = new File(devicesFilePath);
+        try {
+            FileReader reader = new FileReader(devicesFile);
+            BufferedReader bufferedReader = new BufferedReader(reader);
+            String line = "";
+            while ((line = bufferedReader.readLine()) != null) {
+                if (isLineDeviceRecord(line)) {
+                    AlsaDeviceRecord deviceRecord = new AlsaDeviceRecord();
+                    deviceRecord.parse(line);
+                    deviceRecords_.add(deviceRecord);
+                }
+            }
+            reader.close();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+} // class AlsaDevicesParser
+
diff --git a/core/java/android/alsa/LineTokenizer.java b/core/java/android/alsa/LineTokenizer.java
new file mode 100644
index 0000000..c138fc5
--- /dev/null
+++ b/core/java/android/alsa/LineTokenizer.java
@@ -0,0 +1,57 @@
+/*
+ * 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.alsascan;
+
+/**
+ * @hide
+ * Breaks lines in an ALSA "cards" or "devices" file into tokens.
+ * TODO(pmclean) Look into replacing this with String.split().
+ */
+public class LineTokenizer {
+    public static final int kTokenNotFound = -1;
+
+    private String mDelimiters = "";
+
+    public LineTokenizer(String delimiters) {
+        mDelimiters = delimiters;
+    }
+
+    int nextToken(String line, int startIndex) {
+        int len = line.length();
+        int offset = startIndex;
+        for (; offset < len; offset++) {
+            if (mDelimiters.indexOf(line.charAt(offset)) == -1) {
+                // past a delimiter
+                break;
+            }
+      }
+
+      return offset < len ? offset : kTokenNotFound;
+    }
+
+    int nextDelimiter(String line, int startIndex) {
+        int len = line.length();
+        int offset = startIndex;
+        for (; offset < len; offset++) {
+            if (mDelimiters.indexOf(line.charAt(offset)) != -1) {
+                // past a delimiter
+                break;
+            }
+        }
+
+      return offset < len ? offset : kTokenNotFound;
+    }
+}
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 d386eff..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);
@@ -605,11 +601,11 @@
     public static final int RECENT_IGNORE_UNAVAILABLE = 0x0002;
 
     /**
-     * Provides a list that also contains recent tasks for user
-     * and related users.
+     * Provides a list that contains recent tasks for all
+     * profiles of a user.
      * @hide
      */
-    public static final int RECENT_INCLUDE_RELATED = 0x0004;
+    public static final int RECENT_INCLUDE_PROFILES = 0x0004;
 
     /**
      * Return a list of the tasks that the user has recently launched, with
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/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 4ca06ed..7036aea 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -124,4 +124,12 @@
             int type, String domain, String path, long mode, long mtime,
             int token, IBackupManager callbackBinder);
 
+    /**
+     * Out of band: instruct the agent to crash within the client process.  This is used
+     * when the backup infrastructure detects a semantic error post-hoc and needs to
+     * pass the problem back to the app.
+     *
+     * @param message The message to be passed to the agent's application in an exception.
+     */
+    void fail(String message);
 }
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 67c772b..3c31f8d 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -128,6 +128,13 @@
 
     Handler mHandler = null;
 
+    Handler getHandler() {
+        if (mHandler == null) {
+            mHandler = new Handler(Looper.getMainLooper());
+        }
+        return mHandler;
+    }
+
     class SharedPrefsSynchronizer implements Runnable {
         public final CountDownLatch mLatch = new CountDownLatch(1);
 
@@ -140,12 +147,9 @@
 
     // Syncing shared preferences deferred writes needs to happen on the main looper thread
     private void waitForSharedPrefs() {
-        if (mHandler == null) {
-            mHandler = new Handler(Looper.getMainLooper());
-        }
-
+        Handler h = getHandler();
         final SharedPrefsSynchronizer s = new SharedPrefsSynchronizer();
-        mHandler.postAtFrontOfQueue(s);
+        h.postAtFrontOfQueue(s);
         try {
             s.mLatch.await();
         } catch (InterruptedException e) { /* ignored */ }
@@ -680,5 +684,23 @@
                 }
             }
         }
+
+        @Override
+        public void fail(String message) {
+            getHandler().post(new FailRunnable(message));
+        }
+    }
+
+    static class FailRunnable implements Runnable {
+        private String mMessage;
+
+        FailRunnable(String message) {
+            mMessage = message;
+        }
+
+        @Override
+        public void run() {
+            throw new IllegalStateException(mMessage);
+        }
     }
 }
diff --git a/core/java/android/app/backup/BackupDataOutput.java b/core/java/android/app/backup/BackupDataOutput.java
index 845784f..fc5fb3d 100644
--- a/core/java/android/app/backup/BackupDataOutput.java
+++ b/core/java/android/app/backup/BackupDataOutput.java
@@ -85,11 +85,6 @@
      * @throws IOException if the write failed
      */
     public int writeEntityHeader(String key, int dataSize) throws IOException {
-        if (key != null && key.charAt(0) >= 0xff00) {
-            if (Process.myUid() != Process.SYSTEM_UID) {
-                throw new IllegalArgumentException("Invalid key " + key);
-            }
-        }
         int result = writeEntityHeader_native(mBackupWriter, key, dataSize);
         if (result >= 0) {
             return result;
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/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 6f1d4f8..f53aa4c 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -71,7 +71,7 @@
     public static final int FLAG_MANAGED_PROFILE = 0x00000020;
 
 
-    public static final int NO_RELATED_GROUP_ID = -1;
+    public static final int NO_PROFILE_GROUP_ID = -1;
 
     public int id;
     public int serialNumber;
@@ -80,7 +80,7 @@
     public int flags;
     public long creationTime;
     public long lastLoggedInTime;
-    public int relatedGroupId;
+    public int profileGroupId;
 
     /** User is only partially created. */
     public boolean partial;
@@ -94,7 +94,7 @@
         this.name = name;
         this.flags = flags;
         this.iconPath = iconPath;
-        this.relatedGroupId = NO_RELATED_GROUP_ID;
+        this.profileGroupId = NO_PROFILE_GROUP_ID;
     }
 
     public boolean isPrimary() {
@@ -137,7 +137,7 @@
         creationTime = orig.creationTime;
         lastLoggedInTime = orig.lastLoggedInTime;
         partial = orig.partial;
-        relatedGroupId = orig.relatedGroupId;
+        profileGroupId = orig.profileGroupId;
     }
 
     public UserHandle getUserHandle() {
@@ -162,7 +162,7 @@
         dest.writeLong(creationTime);
         dest.writeLong(lastLoggedInTime);
         dest.writeInt(partial ? 1 : 0);
-        dest.writeInt(relatedGroupId);
+        dest.writeInt(profileGroupId);
     }
 
     public static final Parcelable.Creator<UserInfo> CREATOR
@@ -184,6 +184,6 @@
         creationTime = source.readLong();
         lastLoggedInTime = source.readLong();
         partial = source.readInt() != 0;
-        relatedGroupId = source.readInt();
+        profileGroupId = source.readInt();
     }
 }
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/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 6e6c06d..1192a45 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -28,13 +28,13 @@
  */
 interface IUserManager {
     UserInfo createUser(in String name, int flags);
-    UserInfo createRelatedUser(in String name, int flags, int relatedUserId);
+    UserInfo createProfileForUser(in String name, int flags, int userHandle);
     boolean removeUser(int userHandle);
     void setUserName(int userHandle, String name);
     void setUserIcon(int userHandle, in Bitmap icon);
     Bitmap getUserIcon(int userHandle);
     List<UserInfo> getUsers(boolean excludeDying);
-    List<UserInfo> getRelatedUsers(int userHandle);
+    List<UserInfo> getProfiles(int userHandle);
     UserInfo getUserInfo(int userHandle);
     boolean isRestricted();
     void setGuestEnabled(boolean enable);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 057f516..3241693 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -16,10 +16,11 @@
 
 package android.os;
 
-import android.net.LocalSocketAddress;
 import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
 import android.util.Log;
-import dalvik.system.Zygote;
+
+import com.android.internal.os.Zygote;
 
 import java.io.BufferedWriter;
 import java.io.DataInputStream;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 1ec5cd5..520a08c 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -410,20 +410,29 @@
     }
 
     /**
-     * Creates a user with the specified name and options.
+     * Renamed, just present to avoid multi project commit.
+     * TODO delete.
+     * @hide
+     */
+    public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
+        return createProfileForUser(name, flags, relatedUserId);
+    }
+
+    /**
+     * Creates a user with the specified name and options as a profile of another user.
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      *
      * @param name the user's name
      * @param flags flags that identify the type of user and other properties.
      * @see UserInfo
-     * @param relatedUserId new user will be related to this user id.
+     * @param userHandle new user will be a profile of this use.
      *
      * @return the UserInfo object for the created user, or null if the user could not be created.
      * @hide
      */
-    public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
+    public UserInfo createProfileForUser(String name, int flags, int userHandle) {
         try {
-            return mService.createRelatedUser(name, flags, relatedUserId);
+            return mService.createProfileForUser(name, flags, userHandle);
         } catch (RemoteException re) {
             Log.w(TAG, "Could not create a user", re);
             return null;
@@ -454,15 +463,26 @@
     }
 
     /**
-     * Returns information for all users related to userId
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
-     * @param userHandle users related to this user id will be returned.
-     * @return the list of related users.
+     * Renaming, left to avoid multi project commit.
+     * TODO Delete.
      * @hide
      */
     public List<UserInfo> getRelatedUsers(int userHandle) {
+        return getProfiles(userHandle);
+    }
+
+    /**
+     * Returns list of the profiles of userHandle including
+     * userHandle itself.
+     * 
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param userHandle profiles of this user will be returned.
+     * @return the list of profiles.
+     * @hide
+     */
+    public List<UserInfo> getProfiles(int userHandle) {
         try {
-            return mService.getRelatedUsers(userHandle);
+            return mService.getProfiles(userHandle);
         } catch (RemoteException re) {
             Log.w(TAG, "Could not get user list", re);
             return null;
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index b97734e..2ef5b66 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -694,6 +694,67 @@
                 return _result;
             }
 
+            public String getPassword() throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                String _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    mRemote.transact(Stub.TRANSACTION_getPassword, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.readString();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
+
+            public void clearPassword() throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    mRemote.transact(Stub.TRANSACTION_clearPassword, _data, _reply, IBinder.FLAG_ONEWAY);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            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();
@@ -846,7 +907,15 @@
 
         static final int TRANSACTION_mkdirs = IBinder.FIRST_CALL_TRANSACTION + 34;
 
-        static final int TRANSACTION_getPasswordType = IBinder.FIRST_CALL_TRANSACTION + 36;
+        static final int TRANSACTION_getPasswordType = IBinder.FIRST_CALL_TRANSACTION + 35;
+
+        static final int TRANSACTION_getPassword = IBinder.FIRST_CALL_TRANSACTION + 36;
+
+        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
@@ -1208,6 +1277,35 @@
                     reply.writeInt(result);
                     return true;
                 }
+                case TRANSACTION_getPassword: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String result = getPassword();
+                    reply.writeNoException();
+                    reply.writeString(result);
+                    return true;
+                }
+                case TRANSACTION_clearPassword: {
+                    data.enforceInterface(DESCRIPTOR);
+                    clearPassword();
+                    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);
         }
@@ -1446,4 +1544,29 @@
      * @return PasswordType
      */
     public int getPasswordType() throws RemoteException;
+
+    /**
+     * Get password from vold
+     * @return password or empty string
+     */
+    public String getPassword() throws RemoteException;
+
+    /**
+     * 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/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index b8635b8..05f3a1c 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -73,7 +73,8 @@
     public static final String[] INDEXABLES_RAW_COLUMNS = new String[] {
             RawData.COLUMN_RANK,
             RawData.COLUMN_TITLE,
-            RawData.COLUMN_SUMMARY,
+            RawData.COLUMN_SUMMARY_ON,
+            RawData.COLUMN_SUMMARY_OFF,
             RawData.COLUMN_KEYWORDS,
             RawData.COLUMN_SCREEN_TITLE,
             RawData.COLUMN_CLASS_NAME,
@@ -123,9 +124,14 @@
         public static final String COLUMN_TITLE = "title";
 
         /**
-         * Summary's raw data.
+         * Summary's raw data when the data is "ON".
          */
-        public static final String COLUMN_SUMMARY = "summary";
+        public static final String COLUMN_SUMMARY_ON = "summaryOn";
+
+        /**
+         * Summary's raw data when the data is "OFF".
+         */
+        public static final String COLUMN_SUMMARY_OFF = "summaryOff";
 
         /**
          * Keywords' raw data.
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/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index a92f89d..4f646e1 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -182,7 +182,7 @@
     public static boolean sSystemRendererDisabled = false;
 
     /** @hide */
-    public static boolean sUseRenderThread = true;
+    public static boolean sUseRenderThread = false;
 
     private boolean mEnabled;
     private boolean mRequested = true;
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 03a053c..ac3274d 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -504,7 +504,7 @@
 
         private String mEnabledInputMethodsStrCache;
         private int mCurrentUserId;
-        private int[] mRelatedUserIds = new int[0];
+        private int[] mCurrentProfileIds = new int[0];
 
         private static void buildEnabledInputMethodsSettingString(
                 StringBuilder builder, Pair<String, ArrayList<String>> pair) {
@@ -537,17 +537,17 @@
             mCurrentUserId = userId;
         }
 
-        public void setRelatedUserIds(int[] relatedUserIds) {
+        public void setCurrentProfileIds(int[] currentProfileIds) {
             synchronized (this) {
-                mRelatedUserIds = relatedUserIds;
+                mCurrentProfileIds = currentProfileIds;
             }
         }
 
-        public boolean isRelatedToOrCurrentUser(int userId) {
+        public boolean isCurrentProfile(int userId) {
             synchronized (this) {
                 if (userId == mCurrentUserId) return true;
-                for (int i = 0; i < mRelatedUserIds.length; i++) {
-                    if (userId == mRelatedUserIds[i]) return true;
+                for (int i = 0; i < mCurrentProfileIds.length; i++) {
+                    if (userId == mCurrentProfileIds[i]) return true;
                 }
                 return false;
             }
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/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 1766f7b..3301cbe 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -26,8 +26,6 @@
 
 import libcore.io.IoUtils;
 
-import dalvik.system.Zygote;
-
 /**
  * Startup class for the wrapper process.
  * @hide
@@ -94,7 +92,7 @@
      * @param niceName The nice name for the application, or null if none.
      * @param targetSdkVersion The target SDK version for the app.
      * @param pipeFd The pipe to which the application's pid should be written, or null if none.
-     * @param args Arguments for {@link RuntimeInit.main}.
+     * @param args Arguments for {@link RuntimeInit#main}.
      */
     public static void execApplication(String invokeWith, String niceName,
             int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
new file mode 100644
index 0000000..c5fa0a1
--- /dev/null
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+
+import dalvik.system.ZygoteHooks;
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+
+/** @hide */
+public final class Zygote {
+    /*
+    * Bit values for "debugFlags" argument.  The definitions are duplicated
+    * in the native code.
+    */
+
+    /** enable debugging over JDWP */
+    public static final int DEBUG_ENABLE_DEBUGGER   = 1;
+    /** enable JNI checks */
+    public static final int DEBUG_ENABLE_CHECKJNI   = 1 << 1;
+    /** enable Java programming language "assert" statements */
+    public static final int DEBUG_ENABLE_ASSERT     = 1 << 2;
+    /** disable the JIT compiler */
+    public static final int DEBUG_ENABLE_SAFEMODE   = 1 << 3;
+    /** Enable logging of third-party JNI activity. */
+    public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
+
+    /** No external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_NONE = 0;
+    /** Single-user external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_SINGLEUSER = 1;
+    /** Multi-user external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_MULTIUSER = 2;
+    /** All multi-user external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_MULTIUSER_ALL = 3;
+
+    private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
+
+    private Zygote() {}
+
+    /**
+     * Forks a new VM instance.  The current VM must have been started
+     * with the -Xzygote flag. <b>NOTE: new instance keeps all
+     * root capabilities. The new process is expected to call capset()</b>.
+     *
+     * @param uid the UNIX uid that the new process should setuid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gid the UNIX gid that the new process should setgid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gids null-ok; a list of UNIX gids that the new process should
+     * setgroups() to after fork and before spawning any threads.
+     * @param debugFlags bit flags that enable debugging features.
+     * @param rlimits null-ok an array of rlimit tuples, with the second
+     * dimension having a length of 3 and representing
+     * (resource, rlim_cur, rlim_max). These are set via the posix
+     * setrlimit(2) call.
+     * @param seInfo null-ok a string specifying SELinux information for
+     * the new process.
+     * @param niceName null-ok a string specifying the process name.
+     * @param fdsToClose an array of ints, holding one or more POSIX
+     * file descriptor numbers that are to be closed by the child
+     * (and replaced by /dev/null) after forking.  An integer value
+     * of -1 in any entry in the array means "ignore this one".
+     *
+     * @return 0 if this is the child, pid of the child
+     * if this is the parent, or -1 on error.
+     */
+    public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
+          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+        VM_HOOKS.preFork();
+        int pid = nativeForkAndSpecialize(
+                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+        VM_HOOKS.postForkCommon();
+        return pid;
+    }
+
+    native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
+          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
+
+    /**
+     * Special method to start the system server process. In addition to the
+     * common actions performed in forkAndSpecialize, the pid of the child
+     * process is recorded such that the death of the child process will cause
+     * zygote to exit.
+     *
+     * @param uid the UNIX uid that the new process should setuid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gid the UNIX gid that the new process should setgid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gids null-ok; a list of UNIX gids that the new process should
+     * setgroups() to after fork and before spawning any threads.
+     * @param debugFlags bit flags that enable debugging features.
+     * @param rlimits null-ok an array of rlimit tuples, with the second
+     * dimension having a length of 3 and representing
+     * (resource, rlim_cur, rlim_max). These are set via the posix
+     * setrlimit(2) call.
+     * @param permittedCapabilities argument for setcap()
+     * @param effectiveCapabilities argument for setcap()
+     *
+     * @return 0 if this is the child, pid of the child
+     * if this is the parent, or -1 on error.
+     */
+    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
+        VM_HOOKS.preFork();
+        int pid = nativeForkSystemServer(
+                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
+        VM_HOOKS.postForkCommon();
+        return pid;
+    }
+
+    native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
+
+    private static void callPostForkChildHooks(int debugFlags) {
+        VM_HOOKS.postForkChild(debugFlags);
+    }
+
+
+    /**
+     * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
+     * This method throws a runtime exception if exec() failed, otherwise, this
+     * method never returns.
+     *
+     * @param command The shell command to execute.
+     */
+    public static void execShell(String command) {
+        String[] args = { "/system/bin/sh", "-c", command };
+        try {
+            Libcore.os.execv(args[0], args);
+        } catch (ErrnoException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Appends quotes shell arguments to the specified string builder.
+     * The arguments are quoted using single-quotes, escaped if necessary,
+     * prefixed with a space, and appended to the command.
+     *
+     * @param command A string builder for the shell command being constructed.
+     * @param args An array of argument strings to be quoted and appended to the command.
+     * @see #execShell(String)
+     */
+    public static void appendQuotedShellArgs(StringBuilder command, String[] args) {
+        for (String arg : args) {
+            command.append(" '").append(arg.replace("'", "'\\''")).append("'");
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index f9a1f89..aad534c 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -24,7 +24,6 @@
 import android.util.Log;
 
 import dalvik.system.PathClassLoader;
-import dalvik.system.Zygote;
 
 import java.io.BufferedReader;
 import java.io.DataInputStream;
@@ -807,7 +806,7 @@
     /**
      * Applies invoke-with system properties to the zygote arguments.
      *
-     * @param parsedArgs non-null; zygote args
+     * @param args non-null; zygote args
      */
     public static void applyInvokeWithSystemProperty(Arguments args) {
         if (args.invokeWith == null && args.niceName != null) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 05c57e8..66cc120 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -32,7 +32,6 @@
 import android.util.Log;
 
 import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
 
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 91056f1..9501f92 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -28,6 +28,7 @@
     boolean checkPattern(in String pattern, int userId);
     void setLockPassword(in String password, int userId);
     boolean checkPassword(in String password, int userId);
+    boolean checkVoldPassword(int userId);
     boolean havePattern(int userId);
     boolean havePassword(int userId);
     void removeUser(int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 4752da5..4504910 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -333,6 +333,20 @@
     }
 
     /**
+     * Check to see if vold already has the password.
+     * Note that this also clears vold's copy of the password.
+     * @return Whether the vold password matches or not.
+     */
+    public boolean checkVoldPassword() {
+        final int userId = getCurrentOrCallingUserId();
+        try {
+            return getLockSettings().checkVoldPassword(userId);
+        } catch (RemoteException re) {
+            return false;
+        }
+    }
+
+    /**
      * Check to see if a password matches any of the passwords stored in the
      * password history.
      *
@@ -550,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/Android.mk b/core/jni/Android.mk
index 51c5a86..711f28a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -151,7 +151,8 @@
 	android_content_res_ObbScanner.cpp \
 	android_content_res_Configuration.cpp \
 	android_animation_PropertyValuesHolder.cpp \
-	com_android_internal_net_NetworkStatsFactory.cpp
+	com_android_internal_net_NetworkStatsFactory.cpp \
+	com_android_internal_os_Zygote.cpp
 
 LOCAL_C_INCLUDES += \
 	$(JNI_H_INCLUDE) \
@@ -177,7 +178,8 @@
 	external/harfbuzz_ng/src \
 	external/zlib \
 	frameworks/opt/emoji \
-	libcore/include
+	libcore/include \
+	$(call include-path-for, audio-utils) \
 
 LOCAL_SHARED_LIBRARIES := \
 	libmemtrack \
@@ -213,7 +215,8 @@
 	libjpeg \
 	libusbhost \
 	libharfbuzz_ng \
-	libz
+	libz \
+	libaudioutils \
 
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 9a7a5f9..4759451 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -178,6 +178,7 @@
 extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
 extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
 extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
+extern int register_com_android_internal_os_Zygote(JNIEnv *env);
 
 static AndroidRuntime* gCurRuntime = NULL;
 
@@ -228,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
@@ -265,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[])
 {
@@ -1244,6 +1250,7 @@
     REG_JNI(register_android_net_TrafficStats),
     REG_JNI(register_android_os_MemoryFile),
     REG_JNI(register_com_android_internal_os_ZygoteInit),
+    REG_JNI(register_com_android_internal_os_Zygote),
     REG_JNI(register_android_hardware_Camera),
     REG_JNI(register_android_hardware_camera2_CameraMetadata),
     REG_JNI(register_android_hardware_SensorManager),
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 79a46fa..162d0c4 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -26,6 +26,7 @@
 #include <utils/Log.h>
 #include <media/AudioSystem.h>
 #include <media/AudioTrack.h>
+#include <audio_utils/primitives.h>
 
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryBase.h>
@@ -550,10 +551,8 @@
             }
             int count = sizeInBytes;
             int16_t *dst = (int16_t *)track->sharedBuffer()->pointer();
-            const int8_t *src = (const int8_t *)(data + offsetInBytes);
-            while (count--) {
-                *dst++ = (int16_t)(*src++^0x80) << 8;
-            }
+            const uint8_t *src = (const uint8_t *)(data + offsetInBytes);
+            memcpy_to_i16_from_u8(dst, src, count);
             // even though we wrote 2*sizeInBytes, we only report sizeInBytes as written to hide
             // the 8bit mixer restriction from the user of this function
             written = sizeInBytes;
@@ -888,17 +887,22 @@
 }
 
 // ----------------------------------------------------------------------------
-static void
+static jint
 android_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level )
 {
     sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
     if (lpTrack == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()");
-        return;
+        return -1;
     }
 
-    lpTrack->setAuxEffectSendLevel(level);
+    status_t status = lpTrack->setAuxEffectSendLevel(level);
+    if (status != NO_ERROR) {
+        ALOGE("AudioTrack::setAuxEffectSendLevel() for level %g failed with status %d",
+                level, status);
+    }
+    return (jint) status;
 }
 
 // ----------------------------------------------------------------------------
@@ -954,7 +958,7 @@
     {"native_get_min_buff_size",
                              "(III)I",   (void *)android_media_AudioTrack_get_min_buff_size},
     {"native_setAuxEffectSendLevel",
-                             "(F)V",     (void *)android_media_AudioTrack_setAuxEffectSendLevel},
+                             "(F)I",     (void *)android_media_AudioTrack_setAuxEffectSendLevel},
     {"native_attachAuxEffect",
                              "(I)I",     (void *)android_media_AudioTrack_attachAuxEffect},
 };
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/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
new file mode 100644
index 0000000..a61fa87
--- /dev/null
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android_runtime/AndroidRuntime.h"
+
+// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
+#include <sys/mount.h>
+#include <linux/fs.h>
+
+#include <grp.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "cutils/fs.h"
+#include "cutils/multiuser.h"
+#include "cutils/sched_policy.h"
+#include "utils/String8.h"
+#include "JNIHelp.h"
+#include "ScopedLocalRef.h"
+#include "ScopedPrimitiveArray.h"
+#include "ScopedUtfChars.h"
+
+#if defined(HAVE_PRCTL)
+#include <sys/prctl.h>
+#endif
+
+#include <selinux/android.h>
+
+#if defined(__linux__)
+#include <sys/personality.h>
+#include <sys/utsname.h>
+#if defined(HAVE_ANDROID_OS)
+#include <sys/capability.h>
+#endif
+#endif
+
+namespace {
+
+using android::String8;
+
+static pid_t gSystemServerPid = 0;
+
+static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
+static jclass gZygoteClass;
+static jmethodID gCallPostForkChildHooks;
+
+// Must match values in com.android.internal.os.Zygote.
+enum MountExternalKind {
+  MOUNT_EXTERNAL_NONE = 0,
+  MOUNT_EXTERNAL_SINGLEUSER = 1,
+  MOUNT_EXTERNAL_MULTIUSER = 2,
+  MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
+};
+
+static void RuntimeAbort(JNIEnv* env) {
+  env->FatalError("RuntimeAbort");
+}
+
+// This signal handler is for zygote mode, since the zygote must reap its children
+static void SigChldHandler(int /*signal_number*/) {
+  pid_t pid;
+  int status;
+
+  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+     // Log process-death status that we care about.  In general it is
+     // not safe to call LOG(...) from a signal handler because of
+     // possible reentrancy.  However, we know a priori that the
+     // current implementation of LOG() is safe to call from a SIGCHLD
+     // handler in the zygote process.  If the LOG() implementation
+     // changes its locking strategy or its use of syscalls within the
+     // lazy-init critical section, its use here may become unsafe.
+    if (WIFEXITED(status)) {
+      if (WEXITSTATUS(status)) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+      } else if (false) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+      }
+    } else if (WIFSIGNALED(status)) {
+      if (WTERMSIG(status) != SIGKILL) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+      } else if (false) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+      }
+#ifdef WCOREDUMP
+      if (WCOREDUMP(status)) {
+        ALOGI("Process %d dumped core.", pid);
+      }
+#endif /* ifdef WCOREDUMP */
+    }
+
+    // If the just-crashed process is the system_server, bring down zygote
+    // so that it is restarted by init and system server will be restarted
+    // from there.
+    if (pid == gSystemServerPid) {
+      ALOGE("Exit zygote because system server (%d) has terminated");
+      kill(getpid(), SIGKILL);
+    }
+  }
+
+  if (pid < 0) {
+    ALOGW("Zygote SIGCHLD error in waitpid: %d", errno);
+  }
+}
+
+// Configures the SIGCHLD handler for the zygote process. This is configured
+// very late, because earlier in the runtime we may fork() and exec()
+// other processes, and we want to waitpid() for those rather than
+// have them be harvested immediately.
+//
+// This ends up being called repeatedly before each fork(), but there's
+// no real harm in that.
+static void SetSigChldHandler() {
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = SigChldHandler;
+
+  int err = sigaction(SIGCHLD, &sa, NULL);
+  if (err < 0) {
+    ALOGW("Error setting SIGCHLD handler: %d", errno);
+  }
+}
+
+// Sets the SIGCHLD handler back to default behavior in zygote children.
+static void UnsetSigChldHandler() {
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = SIG_DFL;
+
+  int err = sigaction(SIGCHLD, &sa, NULL);
+  if (err < 0) {
+    ALOGW("Error unsetting SIGCHLD handler: %d", errno);
+  }
+}
+
+// Calls POSIX setgroups() using the int[] object as an argument.
+// A NULL argument is tolerated.
+static void SetGids(JNIEnv* env, jintArray javaGids) {
+  if (javaGids == NULL) {
+    return;
+  }
+
+  ScopedIntArrayRO gids(env, javaGids);
+  if (gids.get() == NULL) {
+      RuntimeAbort(env);
+  }
+  int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
+  if (rc == -1) {
+    ALOGE("setgroups failed");
+    RuntimeAbort(env);
+  }
+}
+
+// Sets the resource limits via setrlimit(2) for the values in the
+// two-dimensional array of integers that's passed in. The second dimension
+// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
+// treated as an empty array.
+static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
+  if (javaRlimits == NULL) {
+    return;
+  }
+
+  rlimit rlim;
+  memset(&rlim, 0, sizeof(rlim));
+
+  for (int i = 0; i < env->GetArrayLength(javaRlimits); ++i) {
+    ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
+    ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
+    if (javaRlimit.size() != 3) {
+      ALOGE("rlimits array must have a second dimension of size 3");
+      RuntimeAbort(env);
+    }
+
+    rlim.rlim_cur = javaRlimit[1];
+    rlim.rlim_max = javaRlimit[2];
+
+    int rc = setrlimit(javaRlimit[0], &rlim);
+    if (rc == -1) {
+      ALOGE("setrlimit(%d, {%d, %d}) failed", javaRlimit[0], rlim.rlim_cur, rlim.rlim_max);
+      RuntimeAbort(env);
+    }
+  }
+}
+
+#if defined(HAVE_ANDROID_OS)
+
+// The debug malloc library needs to know whether it's the zygote or a child.
+extern "C" int gMallocLeakZygoteChild;
+
+static void EnableKeepCapabilities(JNIEnv* env) {
+  int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+  if (rc == -1) {
+    ALOGE("prctl(PR_SET_KEEPCAPS) failed");
+    RuntimeAbort(env);
+  }
+}
+
+static void DropCapabilitiesBoundingSet(JNIEnv* env) {
+  for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+    int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+    if (rc == -1) {
+      if (errno == EINVAL) {
+        ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
+              "your kernel is compiled with file capabilities support");
+      } else {
+        ALOGE("prctl(PR_CAPBSET_DROP) failed");
+        RuntimeAbort(env);
+      }
+    }
+  }
+}
+
+static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective) {
+  __user_cap_header_struct capheader;
+  memset(&capheader, 0, sizeof(capheader));
+  capheader.version = _LINUX_CAPABILITY_VERSION_3;
+  capheader.pid = 0;
+
+  __user_cap_data_struct capdata[2];
+  memset(&capdata, 0, sizeof(capdata));
+  capdata[0].effective = effective;
+  capdata[1].effective = effective >> 32;
+  capdata[0].permitted = permitted;
+  capdata[1].permitted = permitted >> 32;
+
+  if (capset(&capheader, &capdata[0]) == -1) {
+    ALOGE("capset(%lld, %lld) failed", permitted, effective);
+    RuntimeAbort(env);
+  }
+}
+
+static void SetSchedulerPolicy(JNIEnv* env) {
+  errno = -set_sched_policy(0, SP_DEFAULT);
+  if (errno != 0) {
+    ALOGE("set_sched_policy(0, SP_DEFAULT) failed");
+    RuntimeAbort(env);
+  }
+}
+
+#else
+
+static int gMallocLeakZygoteChild = 0;
+
+static void EnableKeepCapabilities(JNIEnv*) {}
+static void DropCapabilitiesBoundingSet(JNIEnv*) {}
+static void SetCapabilities(JNIEnv*, int64_t, int64_t) {}
+static void SetSchedulerPolicy(JNIEnv*) {}
+
+#endif
+
+// Create a private mount namespace and bind mount appropriate emulated
+// storage for the given user.
+static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
+  if (mount_mode == MOUNT_EXTERNAL_NONE) {
+    return true;
+  }
+
+  // See storage config details at http://source.android.com/tech/storage/
+  userid_t user_id = multiuser_get_user_id(uid);
+
+  // Create a second private mount namespace for our process
+  if (unshare(CLONE_NEWNS) == -1) {
+      ALOGW("Failed to unshare(): %d", errno);
+      return false;
+  }
+
+  // Create bind mounts to expose external storage
+  if (mount_mode == MOUNT_EXTERNAL_MULTIUSER || mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+    // These paths must already be created by init.rc
+    const char* source = getenv("EMULATED_STORAGE_SOURCE");
+    const char* target = getenv("EMULATED_STORAGE_TARGET");
+    const char* legacy = getenv("EXTERNAL_STORAGE");
+    if (source == NULL || target == NULL || legacy == NULL) {
+      ALOGW("Storage environment undefined; unable to provide external storage");
+      return false;
+    }
+
+    // Prepare source paths
+
+    // /mnt/shell/emulated/0
+    const String8 source_user(String8::format("%s/%d", source, user_id));
+    // /storage/emulated/0
+    const String8 target_user(String8::format("%s/%d", target, user_id));
+
+    if (fs_prepare_dir(source_user.string(), 0000, 0, 0) == -1
+        || fs_prepare_dir(target_user.string(), 0000, 0, 0) == -1) {
+      return false;
+    }
+
+    if (mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+      // Mount entire external storage tree for all users
+      if (TEMP_FAILURE_RETRY(mount(source, target, NULL, MS_BIND, NULL)) == -1) {
+        ALOGW("Failed to mount %s to %s :%d", source, target, errno);
+        return false;
+      }
+    } else {
+      // Only mount user-specific external storage
+      if (TEMP_FAILURE_RETRY(
+              mount(source_user.string(), target_user.string(), NULL, MS_BIND, NULL)) == -1) {
+        ALOGW("Failed to mount %s to %s: %d", source_user.string(), target_user.string(), errno);
+        return false;
+      }
+    }
+
+    if (fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
+        return false;
+    }
+
+    // Finally, mount user-specific path into place for legacy users
+    if (TEMP_FAILURE_RETRY(
+            mount(target_user.string(), legacy, NULL, MS_BIND | MS_REC, NULL)) == -1) {
+      ALOGW("Failed to mount %s to %s: %d", target_user.string(), legacy, errno);
+      return false;
+    }
+  } else {
+    ALOGW("Mount mode %d unsupported", mount_mode);
+    return false;
+  }
+
+  return true;
+}
+
+#if defined(__linux__)
+static bool NeedsNoRandomizeWorkaround() {
+#if !defined(__arm__)
+    return false;
+#else
+    int major;
+    int minor;
+    struct utsname uts;
+    if (uname(&uts) == -1) {
+        return false;
+    }
+
+    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+        return false;
+    }
+
+    // Kernels before 3.4.* need the workaround.
+    return (major < 3) || ((major == 3) && (minor < 4));
+#endif
+}
+#endif
+
+// Utility to close down the Zygote socket file descriptors while
+// the child is still running as root with Zygote's privileges.  Each
+// descriptor (if any) is closed via dup2(), replacing it with a valid
+// (open) descriptor to /dev/null.
+
+static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
+  if (!fdsToClose) {
+    return;
+  }
+  jsize count = env->GetArrayLength(fdsToClose);
+  jint *ar = env->GetIntArrayElements(fdsToClose, 0);
+  if (!ar) {
+      ALOGE("Bad fd array");
+      RuntimeAbort(env);
+  }
+  jsize i;
+  int devnull;
+  for (i = 0; i < count; i++) {
+    devnull = open("/dev/null", O_RDWR);
+    if (devnull < 0) {
+      ALOGE("Failed to open /dev/null");
+      RuntimeAbort(env);
+      continue;
+    }
+    ALOGV("Switching descriptor %d to /dev/null: %d", ar[i], errno);
+    if (dup2(devnull, ar[i]) < 0) {
+      ALOGE("Failed dup2() on descriptor %d", ar[i]);
+      RuntimeAbort(env);
+    }
+    close(devnull);
+  }
+}
+
+void SetThreadName(const char* thread_name) {
+  bool hasAt = false;
+  bool hasDot = false;
+  const char* s = thread_name;
+  while (*s) {
+    if (*s == '.') {
+      hasDot = true;
+    } else if (*s == '@') {
+      hasAt = true;
+    }
+    s++;
+  }
+  const int len = s - thread_name;
+  if (len < 15 || hasAt || !hasDot) {
+    s = thread_name;
+  } else {
+    s = thread_name + len - 15;
+  }
+  // pthread_setname_np fails rather than truncating long strings.
+  char buf[16];       // MAX_TASK_COMM_LEN=16 is hard-coded into bionic
+  strlcpy(buf, s, sizeof(buf)-1);
+  errno = pthread_setname_np(pthread_self(), buf);
+  if (errno != 0) {
+    ALOGW("Unable to set the name of current thread to '%s'", buf);
+  }
+}
+
+// Utility routine to fork zygote and specialize the child process.
+static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
+                                     jint debug_flags, jobjectArray javaRlimits,
+                                     jlong permittedCapabilities, jlong effectiveCapabilities,
+                                     jint mount_external,
+                                     jstring java_se_info, jstring java_se_name,
+                                     bool is_system_server, jintArray fdsToClose) {
+  SetSigChldHandler();
+
+  pid_t pid = fork();
+
+  if (pid == 0) {
+    // The child process.
+    gMallocLeakZygoteChild = 1;
+
+    // Clean up any descriptors which must be closed immediately
+    DetachDescriptors(env, fdsToClose);
+
+    // Keep capabilities across UID change, unless we're staying root.
+    if (uid != 0) {
+      EnableKeepCapabilities(env);
+    }
+
+    DropCapabilitiesBoundingSet(env);
+
+    if (!MountEmulatedStorage(uid, mount_external)) {
+      ALOGW("Failed to mount emulated storage: %d", errno);
+      if (errno == ENOTCONN || errno == EROFS) {
+        // When device is actively encrypting, we get ENOTCONN here
+        // since FUSE was mounted before the framework restarted.
+        // When encrypted device is booting, we get EROFS since
+        // FUSE hasn't been created yet by init.
+        // In either case, continue without external storage.
+      } else {
+        ALOGE("Cannot continue without emulated storage");
+        RuntimeAbort(env);
+      }
+    }
+
+    SetGids(env, javaGids);
+
+    SetRLimits(env, javaRlimits);
+
+    int rc = setresgid(gid, gid, gid);
+    if (rc == -1) {
+      ALOGE("setresgid(%d) failed", gid);
+      RuntimeAbort(env);
+    }
+
+    rc = setresuid(uid, uid, uid);
+    if (rc == -1) {
+      ALOGE("setresuid(%d) failed", uid);
+      RuntimeAbort(env);
+    }
+
+#if defined(__linux__)
+    if (NeedsNoRandomizeWorkaround()) {
+        // Work around ARM kernel ASLR lossage (http://b/5817320).
+        int old_personality = personality(0xffffffff);
+        int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
+        if (new_personality == -1) {
+            ALOGW("personality(%d) failed", new_personality);
+        }
+    }
+#endif
+
+    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
+
+    SetSchedulerPolicy(env);
+
+#if defined(HAVE_ANDROID_OS)
+    {  // NOLINT(whitespace/braces)
+      const char* se_info_c_str = NULL;
+      ScopedUtfChars* se_info = NULL;
+      if (java_se_info != NULL) {
+          se_info = new ScopedUtfChars(env, java_se_info);
+          se_info_c_str = se_info->c_str();
+          if (se_info_c_str == NULL) {
+            ALOGE("se_info_c_str == NULL");
+            RuntimeAbort(env);
+          }
+      }
+      const char* se_name_c_str = NULL;
+      ScopedUtfChars* se_name = NULL;
+      if (java_se_name != NULL) {
+          se_name = new ScopedUtfChars(env, java_se_name);
+          se_name_c_str = se_name->c_str();
+          if (se_name_c_str == NULL) {
+            ALOGE("se_name_c_str == NULL");
+            RuntimeAbort(env);
+          }
+      }
+      rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
+      if (rc == -1) {
+        ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+              is_system_server, se_info_c_str, se_name_c_str);
+        RuntimeAbort(env);
+      }
+
+      // Make it easier to debug audit logs by setting the main thread's name to the
+      // nice name rather than "app_process".
+      if (se_info_c_str == NULL && is_system_server) {
+        se_name_c_str = "system_server";
+      }
+      if (se_info_c_str != NULL) {
+        SetThreadName(se_name_c_str);
+      }
+
+      delete se_info;
+      delete se_name;
+    }
+#else
+    UNUSED(is_system_server);
+    UNUSED(java_se_info);
+    UNUSED(java_se_name);
+#endif
+
+    UnsetSigChldHandler();
+
+    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+    if (env->ExceptionCheck()) {
+      ALOGE("Error calling post fork hooks.");
+      RuntimeAbort(env);
+    }
+  } else if (pid > 0) {
+    // the parent process
+  }
+  return pid;
+}
+}  // anonymous namespace
+
+namespace android {
+
+static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
+        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
+        jint debug_flags, jobjectArray rlimits,
+        jint mount_external, jstring se_info, jstring se_name,
+        jintArray fdsToClose) {
+    return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
+            rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose);
+}
+
+static jint com_android_internal_os_Zygote_nativeForkSystemServer(
+        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
+        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
+        jlong effectiveCapabilities) {
+  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
+                                      debug_flags, rlimits,
+                                      permittedCapabilities, effectiveCapabilities,
+                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL);
+  if (pid > 0) {
+      // The zygote process checks whether the child process has died or not.
+      ALOGI("System server process %d has been created", pid);
+      gSystemServerPid = pid;
+      // There is a slight window that the system server process has crashed
+      // but it went unnoticed because we haven't published its pid yet. So
+      // we recheck here just to make sure that all is well.
+      int status;
+      if (waitpid(pid, &status, WNOHANG) == pid) {
+          ALOGE("System server process %d has died. Restarting Zygote!", pid);
+          RuntimeAbort(env);
+      }
+  }
+  return pid;
+}
+
+static JNINativeMethod gMethods[] = {
+    { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I",
+      (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
+    { "nativeForkSystemServer", "(II[II[[IJJ)I",
+      (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
+};
+
+int register_com_android_internal_os_Zygote(JNIEnv* env) {
+  gZygoteClass = (jclass) env->NewGlobalRef(env->FindClass(kZygoteClassName));
+  if (gZygoteClass == NULL) {
+    RuntimeAbort(env);
+  }
+  gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks", "(I)V");
+
+  return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
+      gMethods, NELEM(gMethods));
+}
+}  // namespace android
+
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-hdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..406bf58
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..409d3cd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..b07da0c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..9d7b25f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index 717ec1a..0000000
--- a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..e49ad54
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..1222711
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..d0fcc25
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-hdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..992a8ff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..51a895d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..2f59488
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..e0a2ba1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..d37e8ee
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..0c604d9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..2c3f4ff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..991c50e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..05fb919
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..219d311
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..bfdc933
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..f31730d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..bd818b5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index c00c545..0000000
--- a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..ebdea00
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..41c7ce6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..961a73e5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-mdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..5903856
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..d38aed2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..87dade3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..ec43047
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..a652117
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..35d1c56
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..264188b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..06ae665
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..a69e301
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..312f76c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..49e0a49
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..8337ffe
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..fb0d0b6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index 1443b7f..0000000
--- a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..f51af63
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..6d87890
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..58f3e0f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..d0d0b1e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..33ec44c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..0166d70
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..a020d64
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..e75ffb8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..1b9fc12
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..f63d47e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..fe005d9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..ea86408
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..65b8d4a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..a397baa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..469f736
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..b56fa4a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index e89c9fe..0000000
--- a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..e8a94dc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..71b9737
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..e2cc715
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
index f220168..605d1de 100644
--- a/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..e1c55ad
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..4b49faf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..561d9ef
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..6fad4a64
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..44d98d5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..c807b50
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..d54f44a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..17c1d99
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..906401e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable/ab_bottom_solid_quantum.xml b/core/res/res/drawable/ab_bottom_solid_quantum.xml
new file mode 100644
index 0000000..848737e
--- /dev/null
+++ b/core/res/res/drawable/ab_bottom_solid_quantum.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_bottom_solid_qntm_alpha"
+    android:tint="?attr/colorBackground"
+    android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ab_bottom_transparent_quantum.xml b/core/res/res/drawable/ab_bottom_transparent_quantum.xml
new file mode 100644
index 0000000..29df6b9
--- /dev/null
+++ b/core/res/res/drawable/ab_bottom_transparent_quantum.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_bottom_transparent_qntm_alpha"
+    android:tint="?attr/colorBackground"
+    android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ab_share_pack_quantum.xml b/core/res/res/drawable/ab_share_pack_quantum.xml
new file mode 100644
index 0000000..7d33ff4d
--- /dev/null
+++ b/core/res/res/drawable/ab_share_pack_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_share_pack_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_solid_quantum.xml b/core/res/res/drawable/ab_solid_quantum.xml
new file mode 100644
index 0000000..e56bb40
--- /dev/null
+++ b/core/res/res/drawable/ab_solid_quantum.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_solid_qntm_alpha"
+    android:tint="?attr/colorBackground"
+    android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ab_solid_shadow_quantum.xml b/core/res/res/drawable/ab_solid_shadow_quantum.xml
new file mode 100644
index 0000000..88e142a
--- /dev/null
+++ b/core/res/res/drawable/ab_solid_shadow_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_solid_shadow_qntm_alpha"
+    android:tint="@color/black" />
diff --git a/core/res/res/drawable/ab_stacked_solid_quantum.xml b/core/res/res/drawable/ab_stacked_solid_quantum.xml
new file mode 100644
index 0000000..df775af
--- /dev/null
+++ b/core/res/res/drawable/ab_stacked_solid_quantum.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_stacked_solid_qntm_alpha"
+    android:tint="?attr/colorBackground"
+    android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ab_stacked_transparent_quantum.xml b/core/res/res/drawable/ab_stacked_transparent_quantum.xml
new file mode 100644
index 0000000..bdae6b9
--- /dev/null
+++ b/core/res/res/drawable/ab_stacked_transparent_quantum.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_stacked_transparent_qntm_alpha"
+    android:tint="?attr/colorBackground"
+    android:tintMode="multiply" />
diff --git a/core/res/res/drawable/btn_cab_done_quantum.xml b/core/res/res/drawable/btn_cab_done_quantum.xml
new file mode 100644
index 0000000..c03ab0a
--- /dev/null
+++ b/core/res/res/drawable/btn_cab_done_quantum.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoMirrored="true">
+    <item android:state_pressed="true">
+        <color android:color="?attr/colorButtonPressed" />
+    </item>
+    <item android:state_focused="true" android:state_enabled="true">
+        <nine-patch android:src="@drawable/btn_cab_done_qntm_alpha"
+            android:tint="?attr/colorButtonPressed" />
+    </item>
+    <item android:state_enabled="true">
+        <nine-patch android:src="@drawable/btn_cab_done_qntm_alpha"
+            android:tint="?attr/colorButtonNormal" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/ic_media_route_connecting_quantum.xml b/core/res/res/drawable/ic_media_route_connecting_quantum.xml
new file mode 100644
index 0000000..0029dd4
--- /dev/null
+++ b/core/res/res/drawable/ic_media_route_connecting_quantum.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="false">
+    <item android:duration="500">
+        <bitmap android:src="@drawable/ic_media_route_on_0_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:duration="500">
+        <bitmap android:src="@drawable/ic_media_route_on_1_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:duration="500">
+        <bitmap android:src="@drawable/ic_media_route_on_2_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:duration="500">
+        <bitmap android:src="@drawable/ic_media_route_on_1_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</animation-list>
diff --git a/core/res/res/drawable/ic_media_route_quantum.xml b/core/res/res/drawable/ic_media_route_quantum.xml
new file mode 100644
index 0000000..16b63d4
--- /dev/null
+++ b/core/res/res/drawable/ic_media_route_quantum.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_enabled="true"
+        android:drawable="@android:drawable/ic_media_route_connecting_quantum" />
+    <item android:state_activated="true" android:state_enabled="true">
+        <bitmap android:src="@android:drawable/ic_media_route_on_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:state_enabled="true">
+        <bitmap android:src="@android:drawable/ic_media_route_off_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item>
+        <bitmap android:src="@android:drawable/ic_media_route_disabled_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</selector>
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/drawable/ratingbar_full_empty_quantum.xml b/core/res/res/drawable/ratingbar_full_empty_quantum.xml
new file mode 100644
index 0000000..e5e4315
--- /dev/null
+++ b/core/res/res/drawable/ratingbar_full_empty_quantum.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_rating_star_off_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_rating_star_off_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/ratingbar_full_filled_quantum.xml b/core/res/res/drawable/ratingbar_full_filled_quantum.xml
new file mode 100644
index 0000000..ad3aa5d
--- /dev/null
+++ b/core/res/res/drawable/ratingbar_full_filled_quantum.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_rating_star_on_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_rating_star_on_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/ratingbar_full_quantum.xml b/core/res/res/drawable/ratingbar_full_quantum.xml
new file mode 100644
index 0000000..143e7c2
--- /dev/null
+++ b/core/res/res/drawable/ratingbar_full_quantum.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@id/background"
+        android:drawable="@drawable/ratingbar_full_empty_quantum" />
+    <item android:id="@id/secondaryProgress"
+        android:drawable="@drawable/ratingbar_full_empty_quantum" />
+    <item android:id="@id/progress" 
+        android:drawable="@drawable/ratingbar_full_filled_quantum" />
+</layer-list>
diff --git a/core/res/res/layout/alert_dialog_progress_quantum.xml b/core/res/res/layout/alert_dialog_progress_quantum.xml
new file mode 100644
index 0000000..b9d0814
--- /dev/null
+++ b/core/res/res/layout/alert_dialog_progress_quantum.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent">
+    <ProgressBar android:id="@+id/progress"
+        style="?android:attr/progressBarStyleHorizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dip"
+        android:layout_marginBottom="1dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip"
+        android:layout_centerHorizontal="true" />
+    <TextView
+        android:id="@+id/progress_percent"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingBottom="16dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip"
+        android:layout_alignParentStart="true"
+        android:layout_below="@id/progress" />
+    <TextView
+        android:id="@+id/progress_number"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingBottom="16dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip"
+        android:layout_alignParentEnd="true"
+        android:layout_below="@id/progress" />
+</RelativeLayout>
diff --git a/core/res/res/layout/alert_dialog_quantum.xml b/core/res/res/layout/alert_dialog_quantum.xml
new file mode 100644
index 0000000..59dba08
--- /dev/null
+++ b/core/res/res/layout/alert_dialog_quantum.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/parentPanel"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <LinearLayout android:id="@+id/topPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <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: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" />
+            <TextView android:id="@+id/alertTitle"
+                style="?android:attr/windowTitleStyle"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="viewStart" />
+        </LinearLayout>
+        <!-- If the client uses a customTitle, it will be added here. -->
+    </LinearLayout>
+
+    <LinearLayout android:id="@+id/contentPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:minHeight="64dp">
+        <ScrollView android:id="@+id/scrollView"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:clipToPadding="false">
+            <TextView android:id="@+id/message"
+                style="?android:attr/textAppearanceMedium"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingStart="16dip"
+                android:paddingEnd="16dip"
+                android:paddingTop="16dip" />
+        </ScrollView>
+    </LinearLayout>
+
+    <FrameLayout android:id="@+id/customPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:minHeight="64dp">
+        <FrameLayout android:id="@+android:id/custom"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+    </FrameLayout>
+
+    <LinearLayout android:id="@+id/buttonPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="@dimen/alert_dialog_button_bar_height"
+        android:orientation="vertical"
+        android:padding="16dip">
+        <LinearLayout
+            style="?android:attr/buttonBarStyle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:layoutDirection="locale"
+            android:measureWithLargestChild="true">
+            <Button android:id="@+id/button3"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="start"
+                android:layout_marginRight="8dip"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                style="?android:attr/buttonBarButtonStyle" />
+            <View android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:layout_weight="1"
+                android:visibility="invisible" />
+            <Button android:id="@+id/button2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                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:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                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/progress_dialog_quantum.xml b/core/res/res/layout/progress_dialog_quantum.xml
new file mode 100644
index 0000000..84d06b5
--- /dev/null
+++ b/core/res/res/layout/progress_dialog_quantum.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <LinearLayout android:id="@+id/body"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:baselineAligned="false"
+        android:padding="16dip">
+
+        <ProgressBar android:id="@android:id/progress"
+            style="?android:attr/progressBarStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:max="10000"
+            android:layout_marginEnd="16dip" />
+
+        <TextView android:id="@+id/message"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical" />
+    </LinearLayout>
+</FrameLayout>
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/layout/select_dialog_item_quantum.xml b/core/res/res/layout/select_dialog_item_quantum.xml
new file mode 100644
index 0000000..59b432e
--- /dev/null
+++ b/core/res/res/layout/select_dialog_item_quantum.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+    This layout file is used by the AlertDialog when displaying a list of items.
+    This layout file is inflated and used as the TextView to display individual
+    items.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:textAppearance="?android:attr/textAppearanceListItemSmall"
+    android:textColor="?android:attr/textColorAlertDialogListItem"
+    android:gravity="center_vertical"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
+    android:ellipsize="marquee" />
diff --git a/core/res/res/layout/select_dialog_multichoice_quantum.xml b/core/res/res/layout/select_dialog_multichoice_quantum.xml
new file mode 100644
index 0000000..8b4c59d
--- /dev/null
+++ b/core/res/res/layout/select_dialog_multichoice_quantum.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:textColor="?android:attr/textColorAlertDialogListItem"
+    android:gravity="center_vertical"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
+    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
+    android:ellipsize="marquee" />
diff --git a/core/res/res/layout/select_dialog_quantum.xml b/core/res/res/layout/select_dialog_quantum.xml
new file mode 100644
index 0000000..ee04039
--- /dev/null
+++ b/core/res/res/layout/select_dialog_quantum.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+    This layout file is used by the AlertDialog when displaying a list of items.
+    This layout file is inflated and used as the ListView to display the items.
+    Assign an ID so its state will be saved/restored.
+-->
+<view class="com.android.internal.app.AlertController$RecycleListView"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+android:id/select_dialog_listview"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:cacheColorHint="@null"
+    android:divider="?android:attr/listDividerAlertDialog"
+    android:scrollbars="vertical"
+    android:overScrollMode="ifContentScrolls"
+    android:textAlignment="viewStart" />
diff --git a/core/res/res/layout/select_dialog_singlechoice_quantum.xml b/core/res/res/layout/select_dialog_singlechoice_quantum.xml
new file mode 100644
index 0000000..27a6648
--- /dev/null
+++ b/core/res/res/layout/select_dialog_singlechoice_quantum.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:textColor="?android:attr/textColorAlertDialogListItem"
+    android:gravity="center_vertical"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
+    android:checkMark="?android:attr/listChoiceIndicatorSingle"
+    android:ellipsize="marquee" />
diff --git a/core/res/res/layout/tab_indicator_quantum.xml b/core/res/res/layout/tab_indicator_quantum.xml
new file mode 100644
index 0000000..fcb2d5f
--- /dev/null
+++ b/core/res/res/layout/tab_indicator_quantum.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="?android:attr/actionBarSize"
+    android:orientation="horizontal"
+    style="@android:style/Widget.Quantum.Tab">
+
+    <ImageView
+        android:id="@android:id/icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:visibility="gone" />
+
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        style="@android:style/Widget.Quantum.TabText" />
+
+</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index f8d7fcc..89b16e9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Laat \'n program toe om toegang tot keyguard se veilige berging te kry."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Beheer wys en versteek van keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Laat \'n program toe om keyguard te beheer."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Luister na vertrouenstaatveranderinge."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Laat \'n program toe om vir veranderinge in vertrouenstaat te luister."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Verbind met \'n vertrouensagentdiens"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Laat \'n program toe om met \'n vertrouensagentdiens te verbind."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Tree in wisselwerking met opdatering- en terugstellingstelsel"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Laat \'n program met die terugstellingstelsel en stelselopdaterings in wisselwerking tree."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Raak twee keer vir zoembeheer"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 0e5a0e7..7703532 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"አንድ መተግበሪያ ደህንነቱ በቁልፍ የተጠበቀ ማከማቻ እንዲደርስ ያስችለዋል።"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"የቁልፍ መጠበቂያውን ማሳየት እና መደበቅ ይቆጣጠሩ"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"አንድ መተግበሪያ የቁልፍ መጠበቂያውን እንዲቆጣጠር ያስችለዋል።"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"የተአማኒነት ሁኔታ ለውጦችን አዳምጥ።"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"መተግበሪያው በተአማኒነት ሁኔታ ውስጥ ለውጦችን እንዲያዳምጥ ይፈቅዳል።"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"ለተአማኒነት ወኪል አገልግሎት ተገዢ አድርግ"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"ለመተግበሪያን የተአማኒነት ወኪል አገልግሎትን እንዲያከብር ይፈቅዳል።"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"ከዝማኔዎች እና ከመልሶ ማግኛ ስርዓቶች ጋር ይገናኙ"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"መተግበሪያው ከመልሶ ማግኛ ስርዓት እና ከስርዓት ማዘመኛዎች ጋር እንዲገናኝ ይፈቅድለታል።"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ለአጉላ መቆጣጠሪያ ሁለት ጊዜ ነካ አድርግ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index c808135..4e04215 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"السماح لأحد التطبيقات بالدخول إلى التخزين المحمي بقفل المفاتيح."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"التحكم في عرض وإخفاء قفل المفاتيح"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"للسماح لأحد التطبيقات بالتحكم في قفل المفاتيح."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"معرفة تغييرات حالة الاعتماد."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"للسماح للتطبيق بالتعرف على التغييرات في حالة الاعتماد."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"الالتزام بخدمة الوكيل المعتمد"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"للسماح لأحد التطبيقات بالالتزام بخدمة الوكيل المعتمد."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"التفاعل مع نظام التحديث والاسترداد"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"للسماح للتطبيق بالتفاعل مع نظام الاسترداد وتحديثات النظام."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"المس مرتين للتحكم في التكبير/التصغير"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 015bf10..0556d7a 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Позволява на приложението да осъществява достъп до надеждното хранилище, свързано с функцията за защита на клавишите."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Контролиране на показването и скриването на функцията за защита на клавишите"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Разрешава на приложението да контролира функцията за защита на клавишите."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Следене за промени в състоянието на надеждност"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Разрешава на приложението да следи за промени в състоянието на надеждност."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Обвързване с услуга за надеждни агенти"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Разрешава на приложението да се обвърже с услуга за надеждни агенти."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Взаимодействие със системата за актуализации и възстановяване"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Разрешава на приложението да взаимодейства със системата за възстановяване и системните актуализации."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Докоснете двукратно за управление на промяната на мащаба"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 94f4b4f..3e8bc78 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permet que una aplicació accedeixi a l\'emmagatzematge protegit per contrasenya."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controla si es mostra o s\'amaga el bloqueig de les tecles."</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permet que una aplicació controli el bloqueig de les tecles."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Escoltar els canvis de l\'estat de confiança"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permet que una aplicació escolti els canvis en l\'estat de confiança."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Enllaçar amb el servei d\'un agent de confiança"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permet que una aplicació es vinculi amb el servei d\'un agent de confiança."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interacciona amb el sistema de recuperació i amb les actualitzacions"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permet que una aplicació interaccioni amb el sistema de recuperació i amb les actualitzacions del sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toca dos cops per controlar el zoom"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b3f482a..0cd8f53 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Umožňuje aplikaci přístup k bezpečnému úložišti keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Ovládání zobrazování a skrývání zámku obrazovky"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Umožňuje aplikaci ovládat zámek obrazovky."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Naslouchat změnám stavu důvěryhodnosti"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Umožňuje aplikaci naslouchat změnám ve stavu důvěryhodnosti."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Vázat se na službu zástupce důvěryhodnosti"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Umožňuje aplikaci vázat se na službu zástupce důvěryhodnosti."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakce se systémem aktualizací a obnovení"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Umožňuje aplikaci interakci se systémem obnovení a s aktualizacemi systému."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dvojitým dotykem můžete ovládat přiblížení"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index a8cf79c..ece8bce 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Tillader, at en applikation får adgang til et nøglebeskyttet lager."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Administrer, om nøglebeskyttelse skal vises eller skjules"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Tillader, at en applikation styrer nøglebeskyttelsen."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Registrer ændringer i tillidstilstand."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Tillader, at en applikation registrerer ændringer i tillidstilstand."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Forpligt til en tillidsagenttjeneste"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Tillader, at en applikation forpligter sig til en tillidsagenttjeneste."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interager med opdaterings- og gendannelsessystemet"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Giver en applikation tilladelse til at interagere med gendannelsessystemet og systemopdateringerne."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Tryk to gange for zoomstyring"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 80a4ed27..639d8ca 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Ermöglicht einer App den Zugriff auf mit Keyguard geschützten Speicher"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Anzeige und Ausblenden des Keyguard steuern"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Apps können den Keyguard steuern."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Auf Änderungen im vertrauenswürdigen Status überwachen"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Ermöglicht einer App die Überwachungen auf Änderungen im vertrauenswürdigen Status"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"An einen Dienst für vertrauenswürdige Anbieter binden"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ermöglicht einer App das Binden an einen Dienst für vertrauenswürdige Anbieter"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Mit Update- und Wiederherstellungssystem interagieren"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Ermöglicht einer App die Interaktion mit dem Wiederherstellungssystem und den Systemupdates"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Für Zoomeinstellung zweimal berühren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index ddee3106..aacb9a2 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Επιτρέπει σε μια εφαρμογή να αποκτήσει πρόσβαση στον ασφαλή αποθηκευτικό χώρο με κλείδωμα."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Έλεγχος εμφάνισης και απόκρυψης κλειδώματος πληκτρολογίου"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Επιτρέπει σε μια εφαρμογή τον έλεγχο του κλειδώματος πληκτρολογίου."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Αντίληψη αλλαγών καταστάσεων εμπιστοσύνης."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Επιτρέπει σε μια εφαρμογή να αντιλαμβάνεται τις αλλαγές στην κατάσταση εμπιστοσύνης."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Σύνδεση σε υπηρεσία έμπιστου αντιπροσώπου"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Επιτρέπει σε μια εφαρμογή να συνδεθεί σε μια υπηρεσία έμπιστου αντιπροσώπου."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Αλληλεπίδραση με το σύστημα ενημέρωσης και ανάκτησης"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Επιτρέπει σε μια εφαρμογή να αλληλεπιδρά με το σύστημα ανάκτησης και ενημερώσεων συστήματος."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Αγγίξτε δύο φορές για έλεγχο εστίασης"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 1c815be..1b2e61b 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Allows an application to access keyguard secure storage."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Control displaying and hiding keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Allows an application to control keyguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Listen to trust state changes."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Allows an application to listen for changes in trust state."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bind to a trust agent service"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Allows an application to bind to a trust agent service."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interact with update and recovery system"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Allows an application to interact with the recovery system and system updates."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Touch twice for zoom control"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 1c815be..1b2e61b 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Allows an application to access keyguard secure storage."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Control displaying and hiding keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Allows an application to control keyguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Listen to trust state changes."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Allows an application to listen for changes in trust state."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bind to a trust agent service"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Allows an application to bind to a trust agent service."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interact with update and recovery system"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Allows an application to interact with the recovery system and system updates."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Touch twice for zoom control"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 16790eb..1483f0f 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite que una aplicación acceda al almacenamiento seguro de bloqueos."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controlar cuándo se muestra y se oculta el bloqueo"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite que una aplicación controle los bloqueos."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Detectar cambios en estado de confianza"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que una aplicación detecte cambios en el estado de confianza."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Vincular con un servicio de agente de confianza"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite que una aplicación se vincule con un servicio de agente de confianza."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interaccionar con el sistema de recuperación y las actualizaciones"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite que una aplicación interaccione con el sistema de recuperación y las actualizaciones del sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toca dos veces para acceder al control de zoom."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d5d9222..3e4b19b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite que una aplicación acceda al almacenamiento seguro de bloqueos."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controlar cuándo se muestra y se oculta el bloqueo"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite que una aplicación controle los bloqueos."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Detectar cambios en estado de confianza."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que una aplicación detecte cambios en el estado de confianza."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Enlazar con un servicio de agente de confianza"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite a una aplicación enlazar con un servicio de agente de confianza."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interactuar con el sistema de recuperación y las actualizaciones"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite que una aplicación interactúe con el sistema de recuperación y las actualizaciones del sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toca dos veces para acceder al control de zoom."</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 12a5ab7..1cb8ba1 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Lubab rakendusel hankida juurdepääsu võtmekaitsega turvalisele talletusruumile."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Võtmekaitse kuvamise ja peitmise juhtimine"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Lubab rakendusel võtmekaitset juhtida."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Usaldusväärse oleku muudatuste tuvastamine."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Lubab rakendusel tuvastada muudatusi usaldusväärses olekus."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Usaldusväärse agendi teenusega sidumine"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Lubab rakendusel ennast siduda usaldusväärse agendi teenusega."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Suhtlemine värskenduse ja taastesüsteemiga"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Lubab rakendusel suhelda taastesüsteemi ja süsteemivärskendustega."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Suumi juhtimiseks puudutage kaks korda"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 5cc9697..ca85f96 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"به یک برنامه کاربردی برای دسترسی به فضای ذخیره‌سازی ایمن محافظ کلید اجازه می‌دهد."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"کنترل نمایش و پنهان کردن محافظ کلید"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"اجازه می‌دهد برنامه‌ای محافظ کلید را کنترل کند."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"گوش دادن به تغییرات حالت اعتماد."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"به یک برنامه کاربردی برای گوش دادن به تغییرات در حالت اعتماد اجازه می‌دهد."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"اتصال به یک سرویس عامل اعتماد"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"به یک برنامه کاربردی برای اتصال به یک سرویس عامل اعتماد اجازه می‌دهد."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"تعامل با سیستم به‌روزرسانی و بازیابی"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"به یک برنامه کاربردی اجازه می‌دهد با سیستم بازیابی و به‌روزرسانی‌های سیستم تعامل داشته باشد."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"دوبار لمس کنید تا بزرگنمایی کنترل شود"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index db118b4..35e8910 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1319,6 +1319,14 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Sallii sovelluksen käyttää salasanalla suojattua tallennustilaa."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Hallinnoi näppäinvahdin näyttämistä ja piilottamista"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Antaa sovelluksen hallita näppäinvahtia."</string>
+    <!-- no translation found for permlab_trust_listener (1765718054003704476) -->
+    <skip />
+    <!-- no translation found for permdesc_trust_listener (8233895334214716864) -->
+    <skip />
+    <!-- no translation found for permlab_bind_trust_agent_service (8242093169457695334) -->
+    <skip />
+    <!-- no translation found for permdesc_bind_trust_agent_service (7041930026024507515) -->
+    <skip />
     <string name="permlab_recovery" msgid="3157024487744125846">"Vuorovaikutus päivitys- ja palautusjärjestelmän kanssa"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Sallii sovelluksen vuorovaikutuksen palautusjärjestelmän ja järjestelmäpäivitysten kanssa."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Ohjaa zoomausta napauttamalla kahdesti"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 9cf9a45..365bbc2 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permet à une application d\'accéder au stockage sécurisé keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Contrôler l\'affichage et le masquage de la protection des touches"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permet à une application de contrôler la protection des touches."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Détecter les modifications de l\'état de confiance"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permet à une application de détecter les modifications de l\'état de confiance."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Lier à un service d\'agent de confiance"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permet à une application de se lier à un service d\'agent de confiance."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagir avec le système de récupération et de mise à jour"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permet à une application d\'interagir avec le système de récupération et les mises à jour système."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Appuyer deux fois pour régler le zoom"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index b10bd342..ff5f106 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permet à une application d\'accéder au stockage sécurisé keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Contrôler l\'affichage et le masquage de la protection des touches"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permet à une application de contrôler la protection des touches."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Détecter les modifications de l\'état de confiance"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permettre à une application de détecter les modifications de l\'état de confiance."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"S\'associer à un service d\'agent de confiance"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permettre à une application de s\'associer à un service d\'agent de confiance."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagir avec le système de récupération et de mise à jour"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permet à une application d\'interagir avec le système de récupération et les mises à jour du système."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Appuyez deux fois pour régler le zoom."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 62c4576..e61c815 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ऐप्स  को कीगार्ड सुरक्षित संग्रहण एक्सेस करने देती है."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"कीगार्ड दिखाना और छिपाना नियंत्रित करें"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"ऐप्स  को कीगार्ड नियंत्रित करने देती है."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"ट्रस्ट स्थिति बदलावों को सुनें."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"किसी एप्लिकेशन को ट्रस्ट स्थिति के बदलावों को सुनने की अनुमति देती है."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"ट्रस्ट एजेंट सेवा से आबद्ध करना"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"किसी एप्लिकेशन को ट्रस्ट एजेंट सेवा से आबद्ध करने की अनुमति देती है."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"अपडेट और पुनर्प्राप्ति सिस्टम के साथ सहभागिता करें"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"एप्लिकेशन को पुनर्प्राप्ति सिस्टम और सिस्टम अपडेट के साथ सहभागिता करने देती है."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ज़ूम नियंत्रण के लिए दो बार स्पर्श करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fc2601b..38dd782 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Omogućuje aplikaciji pristupanje zaključanoj sigurnoj pohrani."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Upravljanje prikazivanjem i skrivanjem zaključavanja tipkovnice"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Omogućuje aplikaciji upravljanje zaključavanjem tipkovnice."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Prati promjene pouzdanog stanja."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Omogućuje aplikaciji praćenje promjena pouzdanog stanja."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Povezivanje s uslugom pouzdanog predstavnika"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Omogućuje aplikaciji povezivanje s uslugom pouzdanog predstavnika."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakcija s ažuriranjem i sustavom za oporavak"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Omogućuje aplikaciji interakciju sa sustavom za oporavak i ažuriranjima sustava."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dodirnite dvaput za upravljanje zumiranjem"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c0effd2..9047cfa 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Lehetővé teszi egy alkalmazás számára, hogy hozzáférjen a kóddal védett tárhelyhez."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Billentyűzár megjelenítésének és elrejtésének vezérlése"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Lehetővé teszi egy alkalmazás számára a billentyűzár vezérlését."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Trust-állapot változásának figyelése"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Lehetővé teszi, hogy az alkalmazás figyelje a trust-állapot változásait."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Csatlakozás egy trust agent szolgáltatáshoz"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Lehetővé teszi, hogy az alkalmazás egy trust agent szolgáltatáshoz csatlakozzon."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Kapcsolatfelvétel a frissítési és helyreállítási rendszerrel"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Lehetővé teszi egy alkalmazás számára, hogy kapcsolatba lépjen a helyreállítási rendszerrel és a rendszerfrissítésekkel."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Érintse meg kétszer a nagyítás beállításához"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 29a8d07..224a9d2 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1319,6 +1319,14 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Թույլ է տալիս հավելվածին մուտք գործել ստեղնակողպեքով պաշտպանված պահոց:"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Կառավարել ստեղնակողպեքի ցուցադրումը և թաքցնումը"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Թույլ է տալիս հավելվածին կառավարել ստեղնաշարի պաշտպանիչը:"</string>
+    <!-- no translation found for permlab_trust_listener (1765718054003704476) -->
+    <skip />
+    <!-- no translation found for permdesc_trust_listener (8233895334214716864) -->
+    <skip />
+    <!-- no translation found for permlab_bind_trust_agent_service (8242093169457695334) -->
+    <skip />
+    <!-- no translation found for permdesc_bind_trust_agent_service (7041930026024507515) -->
+    <skip />
     <string name="permlab_recovery" msgid="3157024487744125846">"Փոխազդել թարմացման և վերականգնման համակարգի հետ"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Թույլ է տալիս ծրագրին փոխազդել վերականգնման համակարգի և համակարգի թարմացումների հետ:"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Հպեք երկու անգամ` դիտափոխման կարգավորման համար"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 71fd308..38a2144 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Mengizinkan aplikasi mengakses pengaman penyimpanan aman."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontrol untuk menampilkan dan menyembunyikan pengaman"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Izinkan aplikasi untuk mengontrol pengaman."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Dengarkan perubahan status kepercayaan."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Mengizinkan aplikasi mendengarkan perubahan dalam status kepercayaan."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Ikat ke layanan agen kepercayaan"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Mengizinkan aplikasi mengikat ke layanan agen kepercayaan."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Berinteraksi dengan sistem pemulihan dan pembaruan"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Mengizinkan aplikasi berinteraksi dengan sistem pemulihan dan pembaruan sistem."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Sentuh dua kali untuk mengontrol perbesar/perkecil"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 958f34c..e99cc45 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Consente a un\'applicazione di accedere all\'archivio sicuro keguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controllo della visualizzazione e dell\'occultamento di keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Consente a un\'applicazione di controllare keguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Rilevamento modifiche dello stato trust."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Consente a un\'applicazione di rilevare le modifiche nello stato trust."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Associazione a un servizio trust agent"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Consente a un\'applicazione di associarsi a un servizio trust agent."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interazione con il sistema di ripristino e aggiornamento"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Consente a un\'applicazione di interagire con il sistema di ripristino e con gli aggiornamenti di sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Tocca due volte per il comando dello zoom"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 9ecc437..d19b48a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"מאפשר לאפליקציה לגשת לאחסון המוגן באמצעות מפתח."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"שלוט בהצגה והסתרה של מגן המקלדת"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"מאפשר לאפליקציה לשלוט במגן המקלדת."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"חיפוש שינויים במצב אמון."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"מאפשר לאפליקציה לחפש שינויים במצב אמון."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"איגוד אל שירות סוכן אמון"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"מאפשר לאפליקציה לאגוד אל שירות סוכן אמון."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"אינטראקציה עם מערכת שחזור ועדכונים"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"מאפשרת לאפליקציה ליצור אינטראקציה עם מערכת השחזור ועדכוני מערכת."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"גע פעמיים לבקרת מרחק מתצוגה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a75ee90..9317ee5 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"キーガードセキュアストレージへのアクセスをアプリに許可する"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"キーガードの表示/非表示の制御"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"キーガードの制御をアプリに許可します。"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"信頼状態の変更をリッスン"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"信頼状態の変更をリッスンすることをアプリに許可します。"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"信頼できるエージェントサービスへのバインド"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"信頼できるエージェントサービスにバインドすることをアプリに許可します。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"アップデートと回復システムへのアクセス"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"回復システムとシステムアップデートへのアクセスをアプリに許可します。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ダブルタップでズームコントロール"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 15abf53..e0efe68 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1319,6 +1319,14 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"აპლიკაციას ღილაკების დამცავის უსაფრთხო საცავზე წვდომის უფლება ექნება."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ღილაკების დამცავის გამოჩენისა და დამალვის მართვა"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"აპლიკაციას შეეძლება ღილაკების დამცავის კონტროლი."</string>
+    <!-- no translation found for permlab_trust_listener (1765718054003704476) -->
+    <skip />
+    <!-- no translation found for permdesc_trust_listener (8233895334214716864) -->
+    <skip />
+    <!-- no translation found for permlab_bind_trust_agent_service (8242093169457695334) -->
+    <skip />
+    <!-- no translation found for permdesc_bind_trust_agent_service (7041930026024507515) -->
+    <skip />
     <string name="permlab_recovery" msgid="3157024487744125846">"განახლებასთან და აღდგენის სისტემასთან ინტერაქცია"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"საშუალებას აძლევს აპლიკაციას მოახდინოს აღდგენის სისტემასთან და სისტემის განახლებასთან ინტერაქცია."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"მასშტაბის მართვისთვის შეეხეთ ორჯერ."</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index c2ff0e8..f843cdd 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ឲ្យ​កម្មវិធី​ចូល​​ការ​ផ្ទុក​មាន​សុវត្ថិភាព keguard ។"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ពិនិត្យ​ការ​បង្ហាញ និង​លាក់​ការ​ការពារ"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"ឲ្យ​កម្មវិធី​គ្រប់គ្រង keguard ។"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"ស្ដាប់​ការ​ផ្លាស់ប្ដូរ​ស្ថានភាព​ដែល​ទុកចិត្ត។"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"ឲ្យ​កម្មវិធី​ស្ដាប់​ការ​ផ្លាស់ប្ដូរ​ក្នុង​ស្ថានភាព​ដែល​​ទុកចិត្ត។"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"ភ្ជាប់​ទៅ​សេវាកម្ម​ភ្នាក់ងារ​ដែល​ទុកចិត្ត"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"ឲ្យ​កម្មវិធី​ភ្ជាប់​សេវាកម្ម​ភ្នាក់ងារ​ដែល​ទុក​ចិត្ត។"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"អន្តរកម្ម​ជា​មួយ​បច្ចុប្បន្នភាព និង​ប្រព័ន្ធ​សង្គ្រោះ"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"ឲ្យ​កម្មវិធី​មាន​អន្តរកម្ម​ជា​មួយ​ប្រព័ន្ធ​សង្គ្រោះ និង​បច្ចុប្បន្នភាព​ប្រព័ន្ធ។"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ប៉ះ​ពីរ​ដង ​​ដើម្បី​គ្រប់គ្រង​ការ​ពង្រីក"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8d8eb88..be93447 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"애플리케이션에서 키가드 보안 저장소에 액세스하도록 허용합니다."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"키가드 표시 및 숨기기 설정"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"애플리케이션에서 키가드를 제어하도록 허용합니다."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Trust 상태 변경사항 수신"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"애플리케이션이 Trust 상태에서의 변경사항을 수신할 수 있도록 허용합니다."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Trust Agent 서비스에 연결"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"애플리케이션이 Trust Agent 서비스에 바인딩할 수 있도록 허용합니다."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"업데이트 및 복구 시스템과 상호작용"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"애플리케이션이 복구 시스템 및 시스템 업데이트와 상호작용할 수 있도록 허용합니다."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"확대/축소하려면 두 번 터치하세요."</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 3b31a8e..78d5d1a 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ເຂົ້າເຖິງບ່ອນຈັດເກັບຂໍ້ມູນຄວາມປອດໄພດ້ວຍຄີກາດ."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ຄວບຄຸມການສະແດງ ແລະການເຊື່ອງໂຕລັອກປຸ່ມກົດ"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນສາມາດຄວບຄຸມຄີກາດໄດ້."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"​ຕິດ​ຕາມ​ການ​ປ່ຽນ​ແປງ​ສະ​ຖາ​ນະ​ການ​ເຊື່ອ​ຖືກ."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ຕິດ​ຕາມ​​ການ​ປ່ຽນ​ແປງ​ໃນ​ສະ​ຖາ​ນະ​ການ​ເຊື່ອ​ຖື."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"​ເຊື່ອມ​ໂຍງ​ຫາ​ບໍ​ລິ​ການ​ຕົວ​ແທນ​ການ​ເຊື່ອ​ຖື"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"​ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນເຊື່ອມ​ໂຍງ​ກັບ​ບໍ​ລິ​ການ​ຕົວ​ແທນ​ທີ່​ເຊື່ອ​ຖື​ໄດ້."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"ຕິດຕໍ່ກັບລະບົບອັບເດດ ແລະລະບົບກູ້ຂໍ້ມູນ."</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຕິດຕໍ່ກັບລະບົບກູ້ຂໍ້ມູນ ແລະການອັບເດດລະບົບ."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ແຕະສອງເທື່ອສຳລັບການຄວບຄຸມການຊູມ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 9c01d99..1b4d57c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Programai leidžiama pasiekti „KeyGuard“ saugyklą."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Valdyti „KeyGuard“ rodymą ir slėpimą"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Programai leidžiama valdyti „KeyGuard“."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Atsižvelgti į patikimos būsenos pakeitimus."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Programai leidžiama atsižvelgti į patikimos būsenos pakeitimus."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Susisaistyti su patikimos priemonės paslauga"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Programai leidžiama susisaistyti su patikimos priemonės paslauga."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Sąveikauti su naujiniu ir atkūrimo sistema"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Programai leidžiama sąveikauti su atkūrimo sistema ir sistemos naujiniais."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dukart palieskite, kad valdytumėte mastelio keitimą"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 478c32d..3e86a8e 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Ļauj lietojumprogrammai piekļūt krātuvei, kas aizsargāta ar atslēgu."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Pārvaldīt krātuves rādīšanu un paslēpšanu."</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Ļauj lietojumprogrammai pārvaldīt krātuvi."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Klausīties uzticamības statusa izmaiņas"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Ļauj lietojumprogrammai klausīties uzticamības statusa izmaiņas."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Izveidot savienojumu ar uzticamības pārbaudes pakalpojumu"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ļauj lietojumprogrammai izveidot savienojumu ar uzticamības pārbaudes pakalpojumu."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Mijiedarbošanās ar atjauninājumu un atkopšanas sistēmu"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Ļauj lietojumprogrammai mijiedarboties ar atkopšanas sistēmu un sistēmas atjauninājumiem."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Pieskarieties divreiz, lai kontrolētu tālummaiņu."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index a587992..a52ed6d 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Аппликешн нь хамгаалалттай аюулгүй санд хандах боломжтой."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Түлхүүр хамгаалалтын харуулах болон далдлахыг удирдах"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Аппликешн нь түлхүүр хамгаалагчыг удирдах боломжтой."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Итгэмжлэлд орж буй өөрчлөлтийг мэдэх."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Итгэмжлэлд орж буй өөрчлөлтийг мэдэх боломжийг аппликешнд олгоно."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Итгэмжлэгдсэн төлөөлөгчийн үйлчилгээтэй холбогдох"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Аппликешнд итгэмжлэгдсэн төлөөлөгчтэй холбогдох боломж олгоно."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Шинэчлэлт болон сэргээх системтэй харилцах"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Аппликешнд сэргээх систем болон системийн шинэчлэлтэй харилцах боломж олгоно."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Өсгөх контрол дээр хоёр удаа товшино уу"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index dbf6004..a997bcd 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1319,6 +1319,14 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Membenarkan aplikasi mengakses storan selamat pengawal kekunci."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kawal paparkan dan sembunyikan pengawal kekunci"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Membenarkan aplikasi untuk mengawal pengawal kekunci."</string>
+    <!-- no translation found for permlab_trust_listener (1765718054003704476) -->
+    <skip />
+    <!-- no translation found for permdesc_trust_listener (8233895334214716864) -->
+    <skip />
+    <!-- no translation found for permlab_bind_trust_agent_service (8242093169457695334) -->
+    <skip />
+    <!-- no translation found for permdesc_bind_trust_agent_service (7041930026024507515) -->
+    <skip />
     <string name="permlab_recovery" msgid="3157024487744125846">"Berinteraksi dengan kemas kini dan sistem pemulihan"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Membenarkan aplikasi berinteraksi dengan sistem pemulihan dan kemas kini sistem."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Sentuh dua kali untuk mendapatkan kawalan zum"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 12d18e0..e5f5a03 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Lar en app bruke sikker lagring via keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontrollér om tastelåsen er skjult eller vist"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Tillater at en app kontrollerer tastelåsen."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Oppdag endringer i pålitelighetsstatusen."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Gir appen tillatelse til å oppdage endringer i pålitelighetsstatusen."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Tilknytt en pålitelighetstagent-tjeneste."</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Gir appen tillatelse til å knyttes til en pålitelighetsagent-tjeneste."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Samhandling med oppdateringer og gjenopprettingssystem"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Tillater en app å samhandle med gjenopprettingsssystemet og systemoppdateringer."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Trykk to ganger for zoomkontroll"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 2c02916..59d662a 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Hiermee krijgt een app toegang tot opslag met toetsbeveiliging."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Weergeven en verbergen van toetsbeveiliging beheren"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Staat toe dat een app de toetsbeveiliging beheert."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Controleren op wijzigingen in de trust-status."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Toestaan dat een app controleert op wijzigingen in de trust-status."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Binden aan een trust-agentservice"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Toestaan dat een app wordt gebonden aan een trust-agentservice."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interactie met update- en herstelsysteem"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Hiermee kan een app interactie hebben met het herstelsysteem en systeemupdates."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Raak twee keer aan voor zoomregeling"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b2a9184..e888927 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Zezwala aplikacji na dostęp do bezpiecznego magazynu kluczy."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontroluj wyświetlanie i ukrywanie zabezpieczenia kluczami"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Umożliwia aplikacji kontrolowanie zabezpieczenia kluczami."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Monitoruj zmiany w stanie zaufania."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Zezwala aplikacji na monitorowanie zmian w stanie zaufania."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Powiąż z usługą agenta zaufania"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Zezwala aplikacji na powiązanie z usługą agenta zaufania."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakcja z systemem odzyskiwania i aktualizacjami"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Zezwala aplikacji na interakcję z systemem odzyskiwania i aktualizacjami systemu."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dotknij dwukrotnie, aby sterować powiększeniem."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3e55c58..43a5b68 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite a uma aplicação aceder ao armazenamento seguro de proteção de teclado."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controlar apresentação e ocultação de proteção de teclado"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite que uma aplicação controle a proteção de teclado."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Registar alterações no estado fidedigno."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que uma aplicação registe alterações no estado fidedigno."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Vincular a um serviço de agente fidedigno"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite que uma aplicação fique vinculada a um serviço de agente fidedigno."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagir com o sistema de recuperação e de atualização"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite que uma aplicação interaja com o sistema de recuperação e as atualizações do sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toque duas vezes para controlar o zoom"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index de22fd5..046ad13 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1319,6 +1319,14 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite que o aplicativo acesse o armazenamento seguro do bloqueio de teclado."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controlar a exibição e ocultação do bloqueio de tela"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite que o aplicativo controle o bloqueio de teclado."</string>
+    <!-- no translation found for permlab_trust_listener (1765718054003704476) -->
+    <skip />
+    <!-- no translation found for permdesc_trust_listener (8233895334214716864) -->
+    <skip />
+    <!-- no translation found for permlab_bind_trust_agent_service (8242093169457695334) -->
+    <skip />
+    <!-- no translation found for permdesc_bind_trust_agent_service (7041930026024507515) -->
+    <skip />
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagir com o sistema de atualizações e recuperação"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite que um aplicativo interaja com o sistema de recuperação e as atualizações do sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toque duas vezes para controlar o zoom"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 6c5344b..79f10aa 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -2104,6 +2104,14 @@
     <skip />
     <!-- no translation found for permdesc_control_keyguard (3043732290518629061) -->
     <skip />
+    <!-- no translation found for permlab_trust_listener (1765718054003704476) -->
+    <skip />
+    <!-- no translation found for permdesc_trust_listener (8233895334214716864) -->
+    <skip />
+    <!-- no translation found for permlab_bind_trust_agent_service (8242093169457695334) -->
+    <skip />
+    <!-- no translation found for permdesc_bind_trust_agent_service (7041930026024507515) -->
+    <skip />
     <!-- no translation found for permlab_recovery (3157024487744125846) -->
     <skip />
     <!-- no translation found for permdesc_recovery (8511774533266359571) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index d4f5183..92f9c52 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1319,6 +1319,14 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite unei aplicații să acceseze stocarea securizată când tastatura este blocată."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Stabilește afișarea și ascunderea blocării tastaturii"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite unei aplicații să controleze blocarea tastaturii."</string>
+    <!-- no translation found for permlab_trust_listener (1765718054003704476) -->
+    <skip />
+    <!-- no translation found for permdesc_trust_listener (8233895334214716864) -->
+    <skip />
+    <!-- no translation found for permlab_bind_trust_agent_service (8242093169457695334) -->
+    <skip />
+    <!-- no translation found for permdesc_bind_trust_agent_service (7041930026024507515) -->
+    <skip />
     <string name="permlab_recovery" msgid="3157024487744125846">"Interacțiune cu sistemul de recuperare și de actualizare"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite unei aplicații să interacționeze cu sistemul de recuperare și cu actualizările de sistem."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Atingeţi de două ori pentru a mări/micşora"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index fd0776b..fa1bab5 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Приложение сможет получить доступ к хранилищу ключей."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Управлять отображением хранилища ключей"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Приложение сможет управлять хранилищем ключей."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Отслеживание изменений"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Приложение сможет отслеживать изменения в работе промежуточного агента."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Подключение к промежуточному агенту"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Приложение сможет подключаться к промежуточному агенту."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Взаимодействовать с системой восстановления и обновлениями"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Приложение сможет взаимодействовать с системой восстановления и обновлениями системы."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Нажмите дважды для изменения масштаба"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 899c4f9..59bf1a0 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Umožňuje aplikácii získať prístup k ukladaciemu priestoru zabezpečenému technológiou keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Ovládanie zobrazenia alebo skrytia technológie keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Umožňuje aplikácii ovládať technológiu keyguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Reagovanie na zmeny stavu dôveryhodnosti."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Umožňuje aplikácii reagovať na zmeny stavu dôveryhodnosti."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Viazanie sa na službu zástupcu dôveryhodnosti"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Umožňuje aplikácii viazať sa na službu zástupcu dôveryhodnosti."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakcia so systémom aktualizácií a obnovenia"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Umožňuje aplikácii interakciu so systémom obnovenia a s aktualizáciami systému."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Ovládacie prvky lupy zobrazíte dvojitým dotknutím"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 1302eb8..35607c2 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Aplikaciji omogoča dostop do varne shrambe Keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Nadzira prikaz in skrivanje zaklepanja tipkovnice"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Aplikaciji omogoča nadzor zaklepanja tipkovnice."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Spremljanje sprememb stanja zaupanja."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Aplikaciji dovoli spremljanje sprememb stanja zaupanja."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Povezovanje s storitvijo posrednikov zaupanja"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Aplikaciji dovoli povezovanje s storitvijo posrednikov zaupanja."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Uporaba sistema za posodobitev in obnovitev"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Aplikaciji dovoli uporabo sistema za obnovitev in posodobitev sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dvakrat se dotaknite za nadzor povečave/pomanjšave"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index e636874..ecf78e7 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Дозвољава апликацији да приступа безбедној меморији заштићеној шифром."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Контролиши приказивање и скривање заштите шифром"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Дозвољава апликацији да контролише заштиту шифром."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Праћење промена стања поузданости."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Дозвољава апликацији да прати промене у стању поузданости."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Везивање за услугу поузданог агента"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Дозвољава апликацији да се веже за услугу поузданог агента."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Интеракција са системом за ажурирање и опоравак"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Дозвољава апликацији да ступа у интеракцију са системом за опоравак и ажурирањима система."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Додирните двапут да бисте контролисали зум"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 31e3c9c..016d9da 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Tillåter att en app får åtkomst till säkert keyguard-lagringsutrymme."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontrollera hur knapplåset visas och döljs"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Tillåter att en app kontrollerar knapplåsfunktionen."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Lyssna efter ändringar i betrodda agenters status."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Tillåter att en app lyssnar efter ändringar i den betrodda agentens status."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bind till en tjänst från en betrodd agent"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Tillåter att en app binds vid en tjänst från en betrodd agent."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagera med uppdaterings- och återställningssystemet"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Tillåter att en app interagerar med systemuppdateringar och återställningssystemet."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Tryck två gånger för zoomkontroll"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 84fbf08..9e72fe3 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Inaruhusu programu kufikia hifadhi salama ya ufunguo wa ulinzi."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Dhibiti uonyeshaji na ufichaji wa kilinda-funguo"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Huruhusu programu kudhibiti kilinda-funguo."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Sikiliza mabadiliko ya hali ya kuaminiana."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Huruhusu programu kusikiliza mabadiliko katika hali ya kuaminiana."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Funga kwenye huduma ya dalali wa kuaminiana"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Huruhusu programu kufunga pamoja kwa huduma ya dalali wa kuaminiana."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Ingiliana na sasisho na mfumo wa kurejesha"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Huruhusu programu kuingiliana na mfumo wa kurejesha na sasisho la mfumo."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Gusa mara mbili kwa udhibiti cha kuza"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 57850a1..9890734 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"อนุญาตให้แอปพลิเคชันเข้าถึงพื้นที่จัดเก็บที่รักษาความปลอดภัยด้วยคีย์การ์ด"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ควบคุมการแสดงผลและการซ่อนตัวล็อกปุ่มกด"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"อนุญาตให้แอปพลิเคชันควบคุมตัวล็อกปุ่มกด"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"ฟังการเปลี่ยนแปลงของสถานะความน่าเชื่อถือ"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"อนุญาตให้แอปพลิเคชันฟังการเปลี่ยนแปลงที่มีต่อสถานะความน่าเชื่อถือ"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"ผูกกับบริการของตัวแทนที่เชื่อถือได้"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"อนุญาตให้แอปพลิเคชันผูกกับบริการของตัวแทนที่เชื่อถือได้"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"โต้ตอบกับการอัปเดตและระบบการกู้คืน"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"ช่วยให้แอปพลิเคชันสามารถโต้ตอบกับระบบการกู้คืนและการอัปเดตระบบ"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"แตะสองครั้งเพื่อควบคุมการซูม"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index b91b44c..f1c31b62 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Nagbibigay-daan sa isang application na i-access ang secure na storage ng keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontrolin ang pagpapakita at pagtago sa keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Pinapayagan ang isang application na kontrolin ang keyguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Makinig sa mga pagbabago sa estado ng trust."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Pinapayagan ang isang application na makinig para sa mga pagbabago sa estado ng trust."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Sumailalim sa isang serbisyo ng trust agent"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Pinapayagan ang isang application na sumailalim sa isang serbisyo ng trust agent."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Makipag-ugnay sa system ng pag-update at pagbawi"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Binibigyang-daan ang isang application na makipag-ugnay sa system ng pagbawi at mga pag-update ng system."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Pindutin nang dalawang beses para sa pagkontrol ng zoom"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index dfb21f7..b992aa2 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Bir uygulamanın tuş kilitli güvenli depolamaya erişimine izin verir."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Tuş koruyucuyu görüntülemeyi ve gizlemeyi kontrol et"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Bir uygulamaya tuş koruyucuyu denetleme izni verir."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Güven durumundaki değişiklileri dinle."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Bir uygulamanın, güven durumundaki değişiklikleri dinlemesine izin verir."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Güven aracı hizmetine bağlan"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Bir uygulamanın, güven aracı hizmetine bağlanmasına izin verir."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Güncelleme ve kurtarma sistemiyle etkileşim kur"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Bir uygulamaya, kurtarma sistemi ve sistem güncellemeriyle etkileşim kurma izni verir."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Yakınlaştırma denetimi için iki kez dokunun"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 238293c..7564602 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Дозволяє програмі отримувати доступ до безпечного сховища через клавіатуру."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Керувати відображенням і хованням клавіатури"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Дозволяє програмі керувати клавіатурою."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Відстежувати зміни в стані довіри."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Дозволяє додатку відстежувати зміни в стані довіри."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Прив’язуватися до служби довірчих агентів"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Дозволяє додатку прив’язуватися до служби довірчих агентів."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Взаємодіяти з оновленнями системи та системою відновлення."</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Дозволяє додатку взаємодіяти із системою відновлення й оновленнями системи."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Двічі торкніться, щоб керувати масштабом"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index b0a617f..28d3776 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -323,8 +323,8 @@
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Ngăn người dùng chuyển sang ứng dụng khác."</string>
     <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"truy cập thông tin ứng dụng hiện tại"</string>
     <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Cho phép chủ sở hữu truy xuất thông tin cá nhân về ứng dụng hiện tại ở nền trước của màn hình."</string>
-    <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"giám sát và kiểm soát tất cả hoạt động khởi chạy ứng dụng"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống khởi chạy các hoạt động. Ứng dụng độc hại hoàn toàn có thể làm tổn hại hệ thống. Quyền này chỉ cần cho mục đích phát triển, không dành cho mục đích sử dụng thông thường."</string>
+    <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"giám sát và kiểm soát tất cả hoạt động chạy ứng dụng"</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống chạy các hoạt động. Ứng dụng độc hại hoàn toàn có thể làm tổn hại hệ thống. Quyền này chỉ cần cho mục đích phát triển, không dành cho mục đích sử dụng thông thường."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"gửi truyền phát đã xóa của gói"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"Cho phép ứng dụng truyền phát thông báo cho biết rằng gói ứng dụng đã bị xóa. Ứng dụng độc hại có thể sử dụng quyền này để loại bỏ bất kỳ ứng dụng nào khác đang chạy."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"gửi truyền phát SMS nhận được"</string>
@@ -346,7 +346,7 @@
     <string name="permlab_backup" msgid="470013022865453920">"kiểm soát sao lưu và khôi phục hệ thống"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Cho phép ứng dụng kiểm soát cơ chế sao lưu và khôi phục của hệ thống. Không dành cho các ứng dụng thông thường."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"xác nhận bản sao lưu đầy đủ hoặc khôi phục hoạt động"</string>
-    <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Cho phép ứng dụng khởi chạy UI xác nhận sao lưu toàn bộ. Không dành cho bất kỳ ứng dụng nào."</string>
+    <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Cho phép ứng dụng chạy UI xác nhận sao lưu toàn bộ. Không dành cho bất kỳ ứng dụng nào."</string>
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"hiển thị các cửa sổ trái phép"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Cho phép ứng dụng tạo các cửa sổ dùng cho giao diện người dùng hệ thống nội bộ. Không dành cho các ứng dụng thông thường."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"vẽ trên ứng dụng khác"</string>
@@ -437,8 +437,8 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"sửa đổi bản đồ dịch vụ của Google"</string>
     <string name="permdesc_writeGservices" msgid="1287309437638380229">"Cho phép ứng dụng sửa đổi bản đồ dịch vụ của Google. Không dành cho ứng dụng thông thường."</string>
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"chạy khi khởi động"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Cho phép ứng dụng tự khởi chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến máy tính bảng mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ máy tính bảng do ứng dụng luôn chạy."</string>
-    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Cho phép ứng dụng tự khởi chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến điện thoại mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ điện thoại do ứng dụng luôn chạy."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Cho phép ứng dụng tự chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến máy tính bảng mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ máy tính bảng do ứng dụng luôn chạy."</string>
+    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Cho phép ứng dụng tự chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến điện thoại mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ điện thoại do ứng dụng luôn chạy."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"gửi truyền phát hấp dẫn người xem"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho máy tính bảng bị chậm hoặc không ổn định do khiến máy tính bảng sử dụng quá nhiều bộ nhớ."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho điện thoại bị chậm hoặc không ổn định do khiến điện thoại sử dụng quá nhiều bộ nhớ."</string>
@@ -1149,7 +1149,7 @@
     <string name="webpage_unresponsive" msgid="3272758351138122503">"Trang không phản hồi.\n\nBạn có muốn đóng trang không?"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"Đã chuyển hướng ứng dụng"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> hiện đang chạy."</string>
-    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> được khởi chạy trước tiên."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> được chạy trước tiên."</string>
     <string name="screen_compat_mode_scale" msgid="3202955667675944499">"Tỷ lệ"</string>
     <string name="screen_compat_mode_show" msgid="4013878876486655892">"Luôn hiển thị"</string>
     <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Bật lại chế độ này trong cài đặt Hệ thống &gt; Ứng dụng &gt; Đã tải xuống."</string>
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Cho phép ứng dụng truy cập bộ nhớ an toàn khóa"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kiểm soát việc hiển thị và ẩn tính năng bảo vệ phím"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Cho phép ứng dụng kiểm soát tính năng bảo vệ phím."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Quan sát các thay đổi ở trạng thái đáng tin cậy."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Cho phép ứng dụng quan sát các thay đổi ở trạng thái đáng tin cậy."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Liên kết với một dịch vụ của đại lý đáng tin cậy"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Cho phép ứng dụng liên kết với một dịch vụ của đại lý đáng tin cậy."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Tương tác với hệ thống khôi phục và bản cập nhật"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Cho phép ứng dụng tương tác với hệ thống khôi phục và bản cập nhật hệ thống."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Chạm hai lần để kiểm soát thu phóng"</string>
@@ -1430,7 +1434,7 @@
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
     <string name="activitychooserview_choose_application" msgid="2125168057199941199">"Chọn một ứng dụng"</string>
-    <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"Không thể khởi chạy <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"Không thể chạy <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Chia sẻ với"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Chia sẻ với <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Tay trượt. Chạm &amp; giữ."</string>
@@ -1479,7 +1483,7 @@
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Chia sẻ với"</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
     <string name="sending" msgid="3245653681008218030">"Đang gửi…"</string>
-    <string name="launchBrowserDefault" msgid="2057951947297614725">"Khởi chạy trình duyệt?"</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Chạy trình duyệt?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Chấp nhận cuộc gọi?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Luôn chọn"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Chỉ một lần"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 902533a..382268c 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"允许应用访问密钥保护安全存储空间。"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"控制是显示还是隐藏锁屏"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"允许应用控制锁屏。"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"检测信任状态的变化。"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"允许应用检测信任状态的变化。"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"绑定至信任的代理服务"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允许应用绑定至信任的代理服务。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"与更新和恢复系统互动"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"允许应用与恢复系统和系统更新互动。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"触摸两次可进行缩放控制"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index d189060..e892f31 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"允許應用程式存取 Keyguard 安全儲存空間。"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"控制顯示或隱藏鍵盤鎖"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"允許應用程式控制鍵盤鎖。"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"聽取信任狀態變更。"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"允許應用程式聽取信任狀態的變更。"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"繫結至信任的代理程式服務"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允許應用程式繫結至信任的代理程式服務。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"與更新和復原系統互動"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"允許應用程式與復原系統和系統更新互動。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"輕觸兩下即可控制縮放"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index dcdfd28..df2daa3 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"允許應用程式存取 Keyguard 安全儲存空間。"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"控制鍵盤鎖的顯示和隱藏"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"允許應用程式控制鍵盤鎖。"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"接聽信任狀態變更。"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"允許應用程式接聽信任狀態變更。"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"繫結至信任的代理程式服務"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允許應用程式繫結至信任的代理程式服務。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"與更新和還原系統互動"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"允許應用程式與還原系統及系統更新互動。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"輕觸兩下即可控制縮放"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 1b12907..fd2134d 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1319,6 +1319,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Ivumela uhlelo lokusebenza ukuthi lufinyelele kusitoreji esiqashwa ngesikhiya esiphephile."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Lawula ukubonisa nokufihla ukhiye wokuqapha"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Ivumela uhlelo lokusebenza ukuthi lulawule ukhiye wokuqapha."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Lalela izinguquko zesimo sokuthemba."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Ivumela uhlelo lokusebenza ukuthi lilalelele izinguquko kusimo sethemba."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bophezela kusevisi yomenzeli wethemba"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ivumela uhlelo lokusebenza ukuthi libophezeleke kusevisi yomenzeli wethemba."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Ixhumana nesibuyekezo nesistimu yokutakula"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Ivumela uhlelo lokusebenza ukuthi lixhumane nesistimu yokutakula nezibuyekezo zesistimu."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Thinta kabili ukulawula ukusondeza"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 369dda1..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" />
@@ -1677,6 +1675,7 @@
              that is, when in portrait. Can be either an absolute dimension
              or a fraction of the screen size in that dimension. -->
         <attr name="windowFixedHeightMajor" format="dimension|fraction" />
+        <attr name="windowOutsetBottom" format="dimension" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -4555,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 13edf6a..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>
@@ -630,8 +621,8 @@
     </style>
 
     <style name="Widget.Quantum.RatingBar" parent="Widget.RatingBar">
-        <item name="progressDrawable">@drawable/ratingbar_full_holo_dark</item>
-        <item name="indeterminateDrawable">@drawable/ratingbar_full_holo_dark</item>
+        <item name="progressDrawable">@drawable/ratingbar_full_quantum</item>
+        <item name="indeterminateDrawable">@drawable/ratingbar_full_quantum</item>
     </style>
 
     <style name="Widget.Quantum.RatingBar.Indicator" parent="Widget.RatingBar.Indicator">
@@ -677,7 +668,7 @@
         <item name="showDividers">middle</item>
         <item name="dividerPadding">8dip</item>
         <item name="measureWithLargestChild">true</item>
-        <item name="tabLayout">@layout/tab_indicator_holo</item>
+        <item name="tabLayout">@layout/tab_indicator_quantum</item>
     </style>
 
     <style name="Widget.Quantum.Tab" parent="Widget.Quantum.ActionBar.TabView">
@@ -731,7 +722,7 @@
     </style>
 
     <style name="Widget.Quantum.ActionButton.CloseMode">
-        <item name="background">@drawable/btn_cab_done_holo_dark</item>
+        <item name="background">@drawable/btn_cab_done_quantum</item>
     </style>
 
     <style name="Widget.Quantum.ActionButton.Overflow">
@@ -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>
@@ -768,8 +759,8 @@
         <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
         <item name="background">@drawable/ab_transparent_quantum</item>
-        <item name="backgroundStacked">@drawable/ab_stacked_transparent_dark_holo</item>
-        <item name="backgroundSplit">@drawable/ab_bottom_transparent_dark_holo</item>
+        <item name="backgroundStacked">@drawable/ab_stacked_transparent_quantum</item>
+        <item name="backgroundSplit">@drawable/ab_bottom_transparent_quantum</item>
         <item name="divider">?attr/dividerVertical</item>
         <item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
@@ -780,9 +771,9 @@
     <style name="Widget.Quantum.ActionBar.Solid">
         <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
-        <item name="background">@drawable/ab_solid_dark_holo</item>
-        <item name="backgroundStacked">@drawable/ab_stacked_solid_dark_holo</item>
-        <item name="backgroundSplit">@drawable/ab_bottom_solid_dark_holo</item>
+        <item name="background">@drawable/ab_solid_quantum</item>
+        <item name="backgroundStacked">@drawable/ab_stacked_solid_quantum</item>
+        <item name="backgroundSplit">@drawable/ab_bottom_solid_quantum</item>
         <item name="divider">?attr/dividerVertical</item>
         <item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
@@ -809,7 +800,7 @@
 
     <style name="Widget.Quantum.MediaRouteButton">
         <item name="background">?attr/selectableItemBackground</item>
-        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_holo_dark</item>
+        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_quantum</item>
         <item name="minWidth">56dp</item>
         <item name="minHeight">48dp</item>
         <item name="focusable">true</item>
@@ -896,7 +887,7 @@
     <style name="Widget.Quantum.Light.DatePicker" parent="Widget.Quantum.DatePicker"/>
 
     <style name="Widget.Quantum.Light.ActivityChooserView" parent="Widget.Quantum.ActivityChooserView">
-        <item name="background">@drawable/ab_share_pack_holo_light</item>
+        <item name="background">@drawable/ab_share_pack_quantum</item>
     </style>
 
     <style name="Widget.Quantum.Light.ImageWell" parent="Widget.Quantum.ImageWell"/>
@@ -919,10 +910,7 @@
     <style name="Widget.Quantum.Light.ProgressBar.Large.Inverse" parent="Widget.Quantum.ProgressBar.Large.Inverse"/>
     <style name="Widget.Quantum.Light.SeekBar" parent="Widget.Quantum.SeekBar"/>
 
-    <style name="Widget.Quantum.Light.RatingBar" parent="Widget.RatingBar">
-        <item name="progressDrawable">@drawable/ratingbar_full_holo_light</item>
-        <item name="indeterminateDrawable">@drawable/ratingbar_full_holo_light</item>
-    </style>
+    <style name="Widget.Quantum.Light.RatingBar" parent="Widget.Quantum.RatingBar" />
 
     <style name="Widget.Quantum.Light.RatingBar.Indicator" parent="Widget.RatingBar.Indicator">
         <item name="progressDrawable">@drawable/ratingbar_holo_light</item>
@@ -991,15 +979,15 @@
     </style>
 
     <style name="Widget.Quantum.Light.ActionButton.CloseMode">
-        <item name="background">@drawable/btn_cab_done_holo_light</item>
+        <item name="background">@drawable/btn_cab_done_quantum</item>
     </style>
 
     <style name="Widget.Quantum.Light.ActionBar" parent="Widget.Quantum.ActionBar">
         <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
         <item name="background">@drawable/ab_transparent_quantum</item>
-        <item name="backgroundStacked">@drawable/ab_stacked_transparent_light_holo</item>
-        <item name="backgroundSplit">@drawable/ab_bottom_transparent_light_holo</item>
+        <item name="backgroundStacked">@drawable/ab_stacked_transparent_quantum</item>
+        <item name="backgroundSplit">@drawable/ab_bottom_transparent_quantum</item>
         <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum</item>
         <item name="progressBarStyle">@style/Widget.Quantum.Light.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.Light.ProgressBar</item>
@@ -1008,9 +996,9 @@
     <style name="Widget.Quantum.Light.ActionBar.Solid">
         <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
-        <item name="background">@drawable/ab_solid_light_holo</item>
-        <item name="backgroundStacked">@drawable/ab_stacked_solid_light_holo</item>
-        <item name="backgroundSplit">@drawable/ab_bottom_solid_light_holo</item>
+        <item name="background">@drawable/ab_solid_quantum</item>
+        <item name="backgroundStacked">@drawable/ab_stacked_solid_quantum</item>
+        <item name="backgroundSplit">@drawable/ab_bottom_solid_quantum</item>
         <item name="divider">?attr/dividerVertical</item>
         <item name="progressBarStyle">@style/Widget.Quantum.Light.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.Light.ProgressBar</item>
@@ -1025,7 +1013,7 @@
     <style name="Widget.Quantum.Light.FastScroll" parent="Widget.Quantum.FastScroll"/>
 
     <style name="Widget.Quantum.Light.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton">
-        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_holo_light</item>
+        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_quantum</item>
     </style>
 
     <!-- Animation Styles -->
@@ -1047,13 +1035,13 @@
         <item name="bottomBright">?attr/colorBackground</item>
         <item name="bottomMedium">?attr/colorBackground</item>
         <item name="centerMedium">?attr/colorBackground</item>
-        <item name="layout">@layout/alert_dialog_holo</item>
-        <item name="listLayout">@layout/select_dialog_holo</item>
-        <item name="progressLayout">@layout/progress_dialog_holo</item>
-        <item name="horizontalProgressLayout">@layout/alert_dialog_progress_holo</item>
-        <item name="listItemLayout">@layout/select_dialog_item_holo</item>
-        <item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_holo</item>
-        <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_holo</item>
+        <item name="layout">@layout/alert_dialog_quantum</item>
+        <item name="listLayout">@layout/select_dialog_quantum</item>
+        <item name="progressLayout">@layout/progress_dialog_quantum</item>
+        <item name="horizontalProgressLayout">@layout/alert_dialog_progress_quantum</item>
+        <item name="listItemLayout">@layout/select_dialog_item_quantum</item>
+        <item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_quantum</item>
+        <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_quantum</item>
     </style>
 
     <style name="AlertDialog.Quantum.Light"/>
@@ -1066,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 24abd55..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>
@@ -476,7 +476,7 @@
         <item name="windowFullscreen">false</item>
         <item name="windowOverscan">false</item>
         <item name="windowIsFloating">false</item>
-        <item name="windowContentOverlay">@drawable/ab_solid_shadow_qntm</item>
+        <item name="windowContentOverlay">@drawable/ab_solid_shadow_quantum</item>
         <item name="windowShowWallpaper">false</item>
         <item name="windowTitleStyle">@style/WindowTitle.Quantum</item>
         <item name="windowTitleSize">25dip</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/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 6d29c69..92ecd24 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -61,7 +61,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014.
 <br/>Any versions with less than 0.1% distribution are not shown.</em>
 </p>
 
@@ -92,7 +92,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014.
 <br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
 
 
@@ -133,17 +133,17 @@
 </tr>
 <tr>
 <td>2.0</th>
-<td>91.1%</td>
+<td>89.4%</td>
 </tr>
 <tr>
 <td>3.0</th>
-<td>8.8%</td>
+<td>10.5%</td>
 </tr>
 </table>
 
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014</em></p>
 
 
 
@@ -161,17 +161,17 @@
 var VERSION_DATA =
 [
   {
-    "chart": "//chart.googleapis.com/chart?chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A1.2%2C19.0%2C0.1%2C15.2%2C62.0%2C2.5&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=500x250&cht=p",
+    "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A1.1%2C17.8%2C0.1%2C14.3%2C61.4%2C5.3&chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat",
     "data": [
       {
         "api": 8,
         "name": "Froyo",
-        "perc": "1.2"
+        "perc": "1.1"
       },
       {
         "api": 10,
         "name": "Gingerbread",
-        "perc": "19.0"
+        "perc": "17.8"
       },
       {
         "api": 13,
@@ -181,27 +181,27 @@
       {
         "api": 15,
         "name": "Ice Cream Sandwich",
-        "perc": "15.2"
+        "perc": "14.3"
       },
       {
         "api": 16,
         "name": "Jelly Bean",
-        "perc": "35.3"
+        "perc": "34.4"
       },
       {
         "api": 17,
         "name": "Jelly Bean",
-        "perc": "17.1"
+        "perc": "18.1"
       },
       {
         "api": 18,
         "name": "Jelly Bean",
-        "perc": "9.6"
+        "perc": "8.9"
       },
       {
         "api": 19,
         "name": "KitKat",
-        "perc": "2.5"
+        "perc": "5.3"
       }
     ]
   }
@@ -218,16 +218,15 @@
       "Large": {
         "hdpi": "0.6",
         "ldpi": "0.7",
-        "mdpi": "4.3",
+        "mdpi": "4.4",
         "tvdpi": "1.5",
         "xhdpi": "0.6"
       },
       "Normal": {
         "hdpi": "33.7",
-        "ldpi": "0.2",
-        "mdpi": "13.6",
-        "xhdpi": "19.9",
-        "xxhdpi": "11.9"
+        "mdpi": "13.2",
+        "xhdpi": "19.8",
+        "xxhdpi": "12.5"
       },
       "Small": {
         "ldpi": "8.1"
@@ -235,12 +234,12 @@
       "Xlarge": {
         "hdpi": "0.3",
         "ldpi": "0.1",
-        "mdpi": "4.3",
-        "xhdpi": "0.2"
+        "mdpi": "4.2",
+        "xhdpi": "0.3"
       }
     },
-    "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A9.1%2C22.2%2C1.5%2C34.6%2C20.7%2C11.9&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p",
-    "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.9%2C7.7%2C79.3%2C8.1&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p"
+    "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A8.9%2C21.8%2C1.5%2C34.6%2C20.7%2C12.6&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi",
+    "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A4.9%2C7.8%2C79.3%2C8.1&chl=Xlarge%7CLarge%7CNormal%7CSmall"
   }
 ];
 
diff --git a/docs/html/google/index.jd b/docs/html/google/index.jd
index b743b66..2e97d62 100644
--- a/docs/html/google/index.jd
+++ b/docs/html/google/index.jd
@@ -125,7 +125,7 @@
 <img src="{@docRoot}images/google/analytics.png" width="40" />
   </div>
     <h4><a class="external-link" 
-href="https://developers.google.com/analytics/devguides/collection/android/v2/"
+href="https://developers.google.com/analytics/devguides/collection/android/v4/"
   >Google Analytics</a></h4>
 
 <p>Measure your success and gain insights into how users engage with your app content
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/html/sdk/installing/studio-build.jd b/docs/html/sdk/installing/studio-build.jd
index 41ad5de..8674134 100644
--- a/docs/html/sdk/installing/studio-build.jd
+++ b/docs/html/sdk/installing/studio-build.jd
@@ -1,4 +1,4 @@
-page.title=Building your Project
+page.title=Building Your Project with Gradle
 
 @jd:body
 
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 0e543e4..c281644 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -37,7 +37,7 @@
           <li><a href="<?cs var:toroot ?>sdk/installing/studio-layout.html">
               Using the Layout Editor</a></li>
           <li><a href="<?cs var:toroot ?>sdk/installing/studio-build.html">
-              Building your Project</a></li>
+              Building Your Project with Gradle</a></li>
           </ul>
       </li>
       <li><a href="<?cs var:toroot ?>sdk/exploring.html">
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index 50485db..c4cb362 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -10,9 +10,9 @@
 
 
 <!-- This is the training bar -->
-<div id="tb-wrapper"> 
-<div id="tb"> 
- 
+<div id="tb-wrapper">
+<div id="tb">
+
 <h2>This lesson teaches you to</h2>
 
 <ol>
@@ -27,10 +27,10 @@
 SDK</a></li>
   <li><a href="{@docRoot}tools/projects/index.html">Managing Projects</a></li>
 </ul>
- 
- 
-</div> 
-</div> 
+
+
+</div>
+</div>
 
 <p>An Android project contains all the files that comprise the source code for your Android
 app. The Android SDK tools make it easy to start a new Android project with a set of
@@ -42,7 +42,7 @@
 
 <p class="note"><strong>Note:</strong> You should already have the Android SDK installed, and if
 you're using Eclipse, you should also have the <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT
-plugin</a> installed (version 21.0.0 or higher). If you don't have these, follow the guide to <a
+plugin</a> installed (version 22.6.2 or higher). If you don't have these, follow the guide to <a
 href="{@docRoot}sdk/installing/index.html">Installing the Android SDK</a> before you start this
 lesson.</p>
 
@@ -50,7 +50,7 @@
 <h2 id="Eclipse">Create a Project with Eclipse</h2>
 
 <ol>
-  <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png" 
+  <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png"
   style="vertical-align:baseline;margin:0" /> in the toolbar.</li>
   <li>In the window that appears, open the <strong>Android</strong> folder,
   select <strong>Android Application Project</strong>, and click <strong>Next</strong>.</li>
@@ -116,11 +116,11 @@
   <li>Now you can select an activity template from which to begin building your app.
     <p>For this project, select <strong>BlankActivity</strong> and click <strong>Next</strong>.</p>
   </li>
-  <li>Leave all the details for the activity in their default state and click 
+  <li>Leave all the details for the activity in their default state and click
     <strong>Finish</strong>.</li>
 </ol>
 
-<p>Your Android project is now a basic "Hello World" app that contains some default files. 
+<p>Your Android project is now a basic "Hello World" app that contains some default files.
 To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
 
 
@@ -155,7 +155,7 @@
 projects.</p></li>
 </ol>
 
-<p>Your Android project is now a basic "Hello World" app that contains some default files. 
+<p>Your Android project is now a basic "Hello World" app that contains some default files.
 To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
 
 <p class="note"><strong>Tip:</strong> Add the <code>platform-tools/</code> as well as the
diff --git a/docs/html/training/basics/firstapp/index.jd b/docs/html/training/basics/firstapp/index.jd
index 4c1a0dc3..1b49096 100644
--- a/docs/html/training/basics/firstapp/index.jd
+++ b/docs/html/training/basics/firstapp/index.jd
@@ -8,21 +8,21 @@
 
 @jd:body
 
-<div id="tb-wrapper"> 
-<div id="tb"> 
- 
-<h2>Dependencies and prerequisites</h2> 
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
 
 <ul>
   <li><a href="http://developer.android.com/sdk/index.html">Android SDK</a></li>
-  <li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> 20.0.0 or higher
+  <li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> 22.6.2 or higher
     (if you're using Eclipse)</li>
 </ul>
- 
-</div> 
-</div> 
- 
-<p>Welcome to Android application development!</p> 
+
+</div>
+</div>
+
+<p>Welcome to Android application development!</p>
 
 <p>This class teaches you how to build your first Android app. You’ll learn how to create an Android
 project and run a debuggable version of the app. You'll also learn some fundamentals of Android app
@@ -36,6 +36,10 @@
   <li>Download the latest SDK tools and platforms using the SDK Manager.</li>
 </ol>
 
+<p class="note"><strong>Note:</strong> Make sure you install the most recent versions of the ADT
+plugin and the Android SDK before you start this class. The procedures described in this class may
+not apply to earlier versions.</p>
+
 <p>If you haven't already done these tasks, start by downloading the
   <a href="{@docRoot}sdk/index.html">Android SDK</a> and following the install steps.
   Once you've finished the setup, you're ready to begin this class.</p>
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index 9aa25a3..27d2c10 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -10,9 +10,9 @@
 
 
 <!-- This is the training bar -->
-<div id="tb-wrapper"> 
-<div id="tb"> 
- 
+<div id="tb-wrapper">
+<div id="tb">
+
 <h2>This lesson teaches you to</h2>
 
 <ol>
@@ -30,10 +30,10 @@
   <li><a href="{@docRoot}sdk/installing/index.html">Installing the
 SDK</a></li>
 </ul>
- 
- 
-</div> 
-</div> 
+
+
+</div>
+</div>
 
 
 
@@ -151,7 +151,7 @@
 </pre>
 
 <p class="note"><strong>Note:</strong>
-You now need an import statement for <code>android.widget.EditText</code>. 
+You now need an import statement for <code>android.widget.EditText</code>.
 You'll define the <code>EXTRA_MESSAGE</code> constant in a moment.</p>
 
 <p>An {@link android.content.Intent} can carry a collection of various data types as key-value
@@ -212,7 +212,7 @@
 <p>To create a new activity using Eclipse:</p>
 
 <ol>
-  <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png" 
+  <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png"
   style="vertical-align:baseline;margin:0" /> in the toolbar.</li>
   <li>In the window that appears, open the <strong>Android</strong> folder
   and select <strong>Android Activity</strong>. Click <strong>Next</strong>.</li>
@@ -247,15 +247,19 @@
   <li>There's also an implementation of {@link android.app.Activity#onOptionsItemSelected
   onOptionsItemSelected()} which handles the behavior for the action bar's <em>Up</em> behavior.
   Keep this one the way it is.</li>
-  <li>There's also a <code>PlaceholderFragment</code> class that extends 
+  <li>There's also a <code>PlaceholderFragment</code> class that extends
 {@link android.app.Fragment}. You will not need this class in the final version of this
 activity.</li>
 </ul>
 
-<p>Fragments decompose application functionality and UI into reusable modules. For more 
-information on fragments, see the <a href="{@docRoot}guide/components/fragments.html">Fragments 
+<p>Fragments decompose application functionality and UI into reusable modules. For more
+information on fragments, see the <a href="{@docRoot}guide/components/fragments.html">Fragments
 API Guide</a>. The final version of this activity does not use fragments.</p>
 
+<p class="note"><strong>Note:</strong> Your activity may look different if you did not use
+the latest version of the ADT plugin. Make sure you install the latest version of the
+<a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT plugin</a> to complete this tutorial.</p>
+
 <p>The {@code DisplayMessageActivity} class should now look like this:</p>
 
 <pre>
diff --git a/docs/html/wear/images/laptop-bridge.png b/docs/html/wear/images/laptop-bridge.png
index b481224..083b82b 100644
--- a/docs/html/wear/images/laptop-bridge.png
+++ b/docs/html/wear/images/laptop-bridge.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/AudioService.java b/media/java/android/media/AudioService.java
index 7f1c5c7..4bd5a80 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -43,6 +43,7 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
+import android.hardware.usb.UsbManager;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
 import android.os.Binder;
@@ -528,6 +529,7 @@
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+        intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
 
         intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         // TODO merge orientation and rotation
@@ -3975,7 +3977,8 @@
                     (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
                 setBluetoothA2dpOnInt(true);
             }
-            boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
+            boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0) ||
+                            ((device & AudioSystem.DEVICE_IN_ALL_USB) != 0);
             handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
             if (state != 0) {
                 if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
@@ -4083,18 +4086,31 @@
             } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
                            action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
                 state = intent.getIntExtra("state", 0);
+
                 int alsaCard = intent.getIntExtra("card", -1);
                 int alsaDevice = intent.getIntExtra("device", -1);
+                boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false);
+                boolean hasCapture = intent.getBooleanExtra("hasCapture", false);
+                boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false);
+
                 String params = (alsaCard == -1 && alsaDevice == -1 ? ""
                                     : "card=" + alsaCard + ";device=" + alsaDevice);
+
+                //TODO(pmclean) - Ignore for now the hasPlayback & hasCapture flags since we
+                // still need to call setWiredDeviceConnectionState() on disconnect (when we
+                // don't have card/device files to parse for this info). We will need to store
+                // that info here when we get smarter about multiple USB card/devices.
+                // Playback Device
                 device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
                         AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE;
-                Log.v(TAG, "Broadcast Receiver: Got "
-                        + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
-                              "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG")
-                        + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice);
                 setWiredDeviceConnectionState(device, state, params);
-            } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
+
+                // Capture Device
+                device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
+                    AudioSystem.DEVICE_IN_USB_ACCESSORY : AudioSystem.DEVICE_IN_USB_DEVICE;
+                setWiredDeviceConnectionState(device, state, params);
+            }
+            else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                 boolean broadcast = false;
                 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
                 synchronized (mScoClients) {
@@ -4199,7 +4215,7 @@
                         mStreamStates[AudioSystem.STREAM_MUSIC], 0);
             }
         }
-    }
+    } // end class AudioServiceBroadcastReceiver
 
     //==========================================================================================
     // RemoteControlDisplay / RemoteControlClient / Remote info
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 9c67bae..327c10c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -288,6 +288,8 @@
                                              DEVICE_IN_USB_DEVICE |
                                              DEVICE_IN_DEFAULT);
     public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+    public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
+                                                 DEVICE_IN_USB_DEVICE);
 
     // device states, must match AudioSystem::device_connection_state
     public static final int DEVICE_STATE_UNAVAILABLE = 0;
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 40c6797..57bc171 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1321,7 +1321,7 @@
      *
      * @param level send level scalar
      * @return error code or success, see {@link #SUCCESS},
-     *    {@link #ERROR_INVALID_OPERATION}
+     *    {@link #ERROR_INVALID_OPERATION}, {@link #ERROR}
      */
     public int setAuxEffectSendLevel(float level) {
         if (isRestricted()) {
@@ -1337,8 +1337,8 @@
         if (level > getMaxVolume()) {
             level = getMaxVolume();
         }
-        native_setAuxEffectSendLevel(level);
-        return SUCCESS;
+        int err = native_setAuxEffectSendLevel(level);
+        return err == 0 ? SUCCESS : ERROR;
     }
 
     //---------------------------------------------------------
@@ -1508,7 +1508,7 @@
             int sampleRateInHz, int channelConfig, int audioFormat);
 
     private native final int native_attachAuxEffect(int effectId);
-    private native final void native_setAuxEffectSendLevel(float level);
+    private native final int native_setAuxEffectSendLevel(float level);
 
     //---------------------------------------------------------
     // Utility methods
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 7170ffb..440653a 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -20,6 +20,8 @@
 import java.util.UUID;
 import java.util.HashMap;
 import java.util.List;
+import android.os.Binder;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -95,12 +97,28 @@
 
     private final static String TAG = "MediaDrm";
 
+    private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
+
     private EventHandler mEventHandler;
     private OnEventListener mOnEventListener;
 
     private long mNativeContext;
 
     /**
+     * Specify no certificate type
+     *
+     * @hide - not part of the public API at this time
+     */
+    public static final int CERTIFICATE_TYPE_NONE = 0;
+
+    /**
+     * Specify X.509 certificate type
+     *
+     * @hide - not part of the public API at this time
+     */
+    public static final int CERTIFICATE_TYPE_X509 = 1;
+
+    /**
      * Query if the given scheme identified by its UUID is supported on
      * this device.
      * @param uuid The UUID of the crypto scheme.
@@ -135,7 +153,7 @@
     }
 
     private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid,
-                                                                      String mimeType);
+            String mimeType);
 
     /**
      * Instantiate a MediaDrm object
@@ -159,7 +177,7 @@
          * It's easier to create it here than in C++.
          */
         native_setup(new WeakReference<MediaDrm>(this),
-                     getByteArrayFromUUID(uuid));
+                getByteArrayFromUUID(uuid));
     }
 
     /**
@@ -268,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) {
@@ -316,6 +334,9 @@
      * Contains the opaque data an app uses to request keys from a license server
      */
     public final static class KeyRequest {
+        private byte[] mData;
+        private String mDefaultUrl;
+
         KeyRequest() {}
 
         /**
@@ -329,9 +350,6 @@
          * server URL from other sources.
          */
         public String getDefaultUrl() { return mDefaultUrl; }
-
-        private byte[] mData;
-        private String mDefaultUrl;
     };
 
     /**
@@ -368,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;
 
 
     /**
@@ -394,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;
 
 
     /**
@@ -456,7 +473,12 @@
      * is returned in ProvisionRequest.data. The recommended URL to deliver the provision
      * request to is returned in ProvisionRequest.defaultUrl.
      */
-    public native ProvisionRequest getProvisionRequest();
+    public ProvisionRequest getProvisionRequest() {
+        return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, "");
+    }
+
+    private native ProvisionRequest getProvisionRequestNative(int certType,
+            String certAuthority);
 
     /**
      * After a provision response is received by the app, it is provided to the DRM
@@ -468,8 +490,13 @@
      * @throws DeniedByServerException if the response indicates that the
      * server rejected the request
      */
-    public native void provideProvisionResponse(byte[] response)
-        throws DeniedByServerException;
+    public void provideProvisionResponse(byte[] response)
+            throws DeniedByServerException {
+        provideProvisionResponseNative(response);
+    }
+
+    private native Certificate provideProvisionResponseNative(byte[] response)
+            throws DeniedByServerException;
 
     /**
      * A means of enforcing limits on the number of concurrent streams per subscriber
@@ -556,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
@@ -602,7 +628,7 @@
         private byte[] mSessionId;
 
         CryptoSession(MediaDrm drm, byte[] sessionId,
-                      String cipherAlgorithm, String macAlgorithm)
+                String cipherAlgorithm, String macAlgorithm)
         {
             mSessionId = sessionId;
             mDrm = drm;
@@ -677,12 +703,124 @@
      * "algorithms".
      */
     public CryptoSession getCryptoSession(byte[] sessionId,
-                                          String cipherAlgorithm,
-                                          String macAlgorithm)
+            String cipherAlgorithm, String macAlgorithm)
     {
         return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm);
     }
 
+    /**
+     * Contains the opaque data an app uses to request a certificate from a provisioning
+     * server
+     *
+     * @hide - not part of the public API at this time
+     */
+    public final static class CertificateRequest {
+        private byte[] mData;
+        private String mDefaultUrl;
+
+        CertificateRequest(byte[] data, String defaultUrl) {
+            mData = data;
+            mDefaultUrl = defaultUrl;
+        }
+
+        /**
+         * Get the opaque message data
+         */
+        public byte[] getData() { return mData; }
+
+        /**
+         * Get the default URL to use when sending the certificate request
+         * message to a server, if known. The app may prefer to use a different
+         * certificate server URL obtained from other sources.
+         */
+        public String getDefaultUrl() { return mDefaultUrl; }
+    }
+
+    /**
+     * Generate a certificate request, specifying the certificate type
+     * and authority. The response received should be passed to
+     * provideCertificateResponse.
+     *
+     * @param certType Specifies the certificate type.
+     *
+     * @param certAuthority is passed to the certificate server to specify
+     * the chain of authority.
+     *
+     * @hide - not part of the public API at this time
+     */
+    public CertificateRequest getCertificateRequest(int certType,
+            String certAuthority)
+    {
+        ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority);
+        return new CertificateRequest(provisionRequest.getData(),
+                provisionRequest.getDefaultUrl());
+    }
+
+    /**
+     * Contains the wrapped private key and public certificate data associated
+     * with a certificate.
+     *
+     * @hide - not part of the public API at this time
+     */
+    public final static class Certificate {
+        Certificate() {}
+
+        /**
+         * Get the wrapped private key data
+         */
+        public byte[] getWrappedPrivateKey() { return mWrappedKey; }
+
+        /**
+         * Get the PEM-encoded certificate chain
+         */
+        public byte[] getContent() { return mCertificateData; }
+
+        private byte[] mWrappedKey;
+        private byte[] mCertificateData;
+    }
+
+
+    /**
+     * Process a response from the certificate server.  The response
+     * is obtained from an HTTP Post to the url provided by getCertificateRequest.
+     * <p>
+     * The public X509 certificate chain and wrapped private key are returned
+     * in the returned Certificate objec.  The certificate chain is in PEM format.
+     * The wrapped private key should be stored in application private
+     * storage, and used when invoking the signRSA method.
+     *
+     * @param response the opaque certificate response byte array to provide to the
+     * DRM engine plugin.
+     *
+     * @throws DeniedByServerException if the response indicates that the
+     * server rejected the request
+     *
+     * @hide - not part of the public API at this time
+     */
+    public Certificate provideCertificateResponse(byte[] response)
+            throws DeniedByServerException {
+        return provideProvisionResponseNative(response);
+    }
+
+    private static final native byte[] signRSANative(MediaDrm drm, byte[] sessionId,
+            String algorithm, byte[] wrappedKey, byte[] message);
+
+    /**
+     * Sign data using an RSA key
+     *
+     * @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
+     * from provideCertificateResponse
+     * @param message the data for which a signature is to be computed
+     *
+     * @hide - not part of the public API at this time
+     */
+    public byte[] signRSA(byte[] sessionId, String algorithm,
+            byte[] wrappedKey, byte[] message) {
+        return signRSANative(this, sessionId, algorithm, wrappedKey, message);
+    }
+
     @Override
     protected void finalize() {
         native_finalize();
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index b2fb2df..d04b1f8 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -27,6 +27,8 @@
 #include "jni.h"
 #include "JNIHelp.h"
 
+#include <cutils/compiler.h>
+
 #include <gui/Surface.h>
 
 #include <media/ICrypto.h>
@@ -738,6 +740,10 @@
     } else if (numBytesOfClearDataObj != NULL
             && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
         err = -ERANGE;
+    // subSamples array may silently overflow if number of samples are too large.  Use
+    // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
+    } else if ( CC_UNLIKELY(numSubSamples >= INT32_MAX / sizeof(*subSamples)) ) {
+        err = -EINVAL;
     } else {
         jboolean isCopy;
 
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 052d97d..7c45682 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -100,6 +100,16 @@
     jint kKeyTypeRelease;
 } gKeyTypes;
 
+struct CertificateTypes {
+    jint kCertificateTypeNone;
+    jint kCertificateTypeX509;
+} gCertificateTypes;
+
+struct CertificateFields {
+    jfieldID wrappedPrivateKey;
+    jfieldID certificateData;
+};
+
 struct fields_t {
     jfieldID context;
     jmethodID post_event;
@@ -110,6 +120,11 @@
     SetFields set;
     IteratorFields iterator;
     EntryFields entry;
+    CertificateFields certificate;
+    jclass certificateClassId;
+    jclass hashmapClassId;
+    jclass arraylistClassId;
+    jclass stringClassId;
 };
 
 static fields_t gFields;
@@ -406,8 +421,7 @@
 */
 
 static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) {
-    jclass clazz;
-    FIND_CLASS(clazz, "java/lang/String");
+    jclass clazz = gFields.stringClassId;
     KeyedVector<String8, String8> keyedVector;
 
     jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
@@ -450,8 +464,7 @@
 }
 
 static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
-    jclass clazz;
-    FIND_CLASS(clazz, "java/util/HashMap");
+    jclass clazz = gFields.hashmapClassId;
     jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
     for (size_t i = 0; i < map.size(); ++i) {
         jstring jkey = env->NewStringUTF(map.keyAt(i).string());
@@ -465,8 +478,7 @@
 
 static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
                                                    List<Vector<uint8_t> > list) {
-    jclass clazz;
-    FIND_CLASS(clazz, "java/util/ArrayList");
+    jclass clazz = gFields.arraylistClassId;
     jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
     List<Vector<uint8_t> >::iterator iter = list.begin();
     while (iter != list.end()) {
@@ -542,6 +554,11 @@
     GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
     gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
 
+    GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
+    gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
+    GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
+    gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
+
     FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
     GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
     GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
@@ -550,6 +567,11 @@
     GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
     GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
 
+    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 = static_cast<jclass>(env->NewGlobalRef(clazz));
+
     FIND_CLASS(clazz, "java/util/ArrayList");
     GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
     GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
@@ -571,6 +593,15 @@
     FIND_CLASS(clazz, "java/util/Map$Entry");
     GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
     GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
+
+    FIND_CLASS(clazz, "java/util/HashMap");
+    gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+    FIND_CLASS(clazz, "java/lang/String");
+    gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+    FIND_CLASS(clazz, "java/util/ArrayList");
+    gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
 }
 
 static void android_media_MediaDrm_native_setup(
@@ -826,8 +857,8 @@
     return KeyedVectorToHashMap(env, infoMap);
 }
 
-static jobject android_media_MediaDrm_getProvisionRequest(
-    JNIEnv *env, jobject thiz) {
+static jobject android_media_MediaDrm_getProvisionRequestNative(
+    JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
     sp<IDrm> drm = GetDrm(env, thiz);
 
     if (drm == NULL) {
@@ -839,7 +870,17 @@
     Vector<uint8_t> request;
     String8 defaultUrl;
 
-    status_t err = drm->getProvisionRequest(request, defaultUrl);
+    String8 certType;
+    if (jcertType == gCertificateTypes.kCertificateTypeX509) {
+        certType = "X.509";
+    } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
+        certType = "none";
+    } else {
+        certType = "invalid";
+    }
+
+    String8 certAuthority = JStringToString8(env, jcertAuthority);
+    status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
 
     if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
         return NULL;
@@ -863,27 +904,43 @@
     return provisionObj;
 }
 
-static void android_media_MediaDrm_provideProvisionResponse(
+static jobject android_media_MediaDrm_provideProvisionResponseNative(
     JNIEnv *env, jobject thiz, jbyteArray jresponse) {
     sp<IDrm> drm = GetDrm(env, thiz);
 
     if (drm == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException",
                           "MediaDrm obj is null");
-        return;
+        return NULL;
     }
 
     if (jresponse == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException",
                           "provision response is null");
-        return;
+        return NULL;
     }
 
     Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
+    Vector<uint8_t> certificate, wrappedKey;
 
-    status_t err = drm->provideProvisionResponse(response);
+    status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
+
+    // Fill out return obj
+    jclass clazz = gFields.certificateClassId;
+
+    jobject certificateObj = NULL;
+
+    if (clazz && certificate.size() && wrappedKey.size()) {
+        certificateObj = env->AllocObject(clazz);
+        jbyteArray jcertificate = VectorToJByteArray(env, certificate);
+        env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
+
+        jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
+        env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
+    }
 
     throwExceptionAsNecessary(env, err, "Failed to handle provision response");
+    return certificateObj;
 }
 
 static jobject android_media_MediaDrm_getSecureStops(
@@ -1209,6 +1266,38 @@
 }
 
 
+static jbyteArray android_media_MediaDrm_signRSANative(
+    JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
+    jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
+
+    sp<IDrm> drm = GetDrm(env, jdrm);
+
+    if (!CheckSession(env, drm, jsessionId)) {
+        return NULL;
+    }
+
+    if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "required argument is null");
+        return NULL;
+    }
+
+    Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
+    String8 algorithm = JStringToString8(env, jalgorithm);
+    Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
+    Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
+    Vector<uint8_t> signature;
+
+    status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
+
+    if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+        return NULL;
+    }
+
+    return VectorToJByteArray(env, signature);
+}
+
+
 static JNINativeMethod gMethods[] = {
     { "release", "()V", (void *)android_media_MediaDrm_release },
     { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
@@ -1244,11 +1333,11 @@
     { "queryKeyStatus", "([B)Ljava/util/HashMap;",
       (void *)android_media_MediaDrm_queryKeyStatus },
 
-    { "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;",
-      (void *)android_media_MediaDrm_getProvisionRequest },
+    { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
+      (void *)android_media_MediaDrm_getProvisionRequestNative },
 
-    { "provideProvisionResponse", "([B)V",
-      (void *)android_media_MediaDrm_provideProvisionResponse },
+    { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
+      (void *)android_media_MediaDrm_provideProvisionResponseNative },
 
     { "getSecureStops", "()Ljava/util/List;",
       (void *)android_media_MediaDrm_getSecureStops },
@@ -1287,6 +1376,9 @@
 
     { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
       (void *)android_media_MediaDrm_verifyNative },
+
+    { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
+      (void *)android_media_MediaDrm_signRSANative },
 };
 
 int register_android_media_Drm(JNIEnv *env) {
diff --git a/media/lib/Android.mk b/media/lib/remotedisplay/Android.mk
similarity index 93%
rename from media/lib/Android.mk
rename to media/lib/remotedisplay/Android.mk
index 50799a6..ea1ac2b 100644
--- a/media/lib/Android.mk
+++ b/media/lib/remotedisplay/Android.mk
@@ -15,7 +15,7 @@
 #
 LOCAL_PATH := $(call my-dir)
 
-# the library
+# the remotedisplay library
 # ============================================================
 include $(CLEAR_VARS)
 
@@ -23,7 +23,7 @@
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_SRC_FILES := \
-            $(call all-subdir-java-files) \
+            $(call all-java-files-under, java) \
             $(call all-aidl-files-under, java)
 
 include $(BUILD_JAVA_LIBRARY)
diff --git a/media/lib/README.txt b/media/lib/remotedisplay/README.txt
similarity index 99%
rename from media/lib/README.txt
rename to media/lib/remotedisplay/README.txt
index cade3df..5738dbe 100644
--- a/media/lib/README.txt
+++ b/media/lib/remotedisplay/README.txt
@@ -25,4 +25,3 @@
 library is a compromise to make new capabilities available to the system
 without exposing the full surface area of the support library media
 route provider protocol.
-
diff --git a/media/lib/com.android.media.remotedisplay.xml b/media/lib/remotedisplay/com.android.media.remotedisplay.xml
similarity index 100%
rename from media/lib/com.android.media.remotedisplay.xml
rename to media/lib/remotedisplay/com.android.media.remotedisplay.xml
diff --git a/media/lib/java/com/android/media/remotedisplay/RemoteDisplay.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java
similarity index 100%
rename from media/lib/java/com/android/media/remotedisplay/RemoteDisplay.java
rename to media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java
diff --git a/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
similarity index 100%
rename from media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
rename to media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
diff --git a/media/lib/Android.mk b/media/lib/signer/Android.mk
similarity index 76%
copy from media/lib/Android.mk
copy to media/lib/signer/Android.mk
index 50799a6..4c3772f 100644
--- a/media/lib/Android.mk
+++ b/media/lib/signer/Android.mk
@@ -15,24 +15,23 @@
 #
 LOCAL_PATH := $(call my-dir)
 
-# the library
+# the mediadrm signer library
 # ============================================================
 include $(CLEAR_VARS)
 
-LOCAL_MODULE:= com.android.media.remotedisplay
+LOCAL_MODULE:= com.android.mediadrm.signer
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_SRC_FILES := \
-            $(call all-subdir-java-files) \
-            $(call all-aidl-files-under, java)
+            $(call all-java-files-under, java)
 
-include $(BUILD_JAVA_LIBRARY)
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 
-# ====  com.android.media.remotedisplay.xml lib def  ========================
+# ====  com.android.mediadrm.signer.xml lib def  ========================
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := com.android.media.remotedisplay.xml
+LOCAL_MODULE := com.android.mediadrm.signer.xml
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_MODULE_CLASS := ETC
diff --git a/media/lib/signer/README.txt b/media/lib/signer/README.txt
new file mode 100644
index 0000000..362ab8e
--- /dev/null
+++ b/media/lib/signer/README.txt
@@ -0,0 +1,28 @@
+This library (com.android.mediadrm.signer.jar) is a shared java library
+containing classes required by unbundled apps running on devices that use
+the certficate provisioning and private key signing capabilities provided
+by the MediaDrm API.
+
+--- Rules of this library ---
+o This library is effectively a PUBLIC API for unbundled CAST receivers
+  that may be distributed outside the system image. So it MUST BE API STABLE.
+  You can add but not remove. The rules are the same as for the
+  public platform SDK API.
+o This library can see and instantiate internal platform classes, but it must not
+  expose them in any public method (or by extending them via inheritance). This would
+  break clients of the library because they cannot see the internal platform classes.
+
+This library is distributed in the system image, and loaded as
+a shared library. So you can change the implementation, but not
+the interface. In this way it is like framework.jar.
+
+--- Why does this library exist? ---
+
+Unbundled apps cannot use internal platform classes.
+
+This library will eventually be replaced when the provisioned certificate-
+based signing infrastructure that is currently defined in the support library
+is reintegrated with the framework in a new API.  That API isn't ready yet so
+this library is a compromise to make new capabilities available to the system
+without exposing the full surface area of the support library.
+
diff --git a/media/lib/signer/com.android.mediadrm.signer.xml b/media/lib/signer/com.android.mediadrm.signer.xml
new file mode 100644
index 0000000..b5b1f09
--- /dev/null
+++ b/media/lib/signer/com.android.mediadrm.signer.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<permissions>
+    <library name="com.android.media.drm.signer"
+            file="/system/framework/com.android.media.drm.signer.jar" />
+</permissions>
diff --git a/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java b/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java
new file mode 100644
index 0000000..0a2897f
--- /dev/null
+++ b/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediadrm.signer;
+
+import android.media.MediaDrm;
+import android.media.DeniedByServerException;
+
+/**
+ * Provides certificate request generation, response handling and
+ * signing APIs
+ */
+public final class MediaDrmSigner {
+    private MediaDrmSigner() {}
+
+    /**
+     * Specify X.509 certificate type
+     */
+    public static final int CERTIFICATE_TYPE_X509 = MediaDrm.CERTIFICATE_TYPE_X509;
+
+    /**
+     * Contains the opaque data an app uses to request a certificate from a provisioning
+     * server
+     */
+    public final static class CertificateRequest {
+        private final MediaDrm.CertificateRequest mCertRequest;
+
+        CertificateRequest(MediaDrm.CertificateRequest certRequest) {
+            mCertRequest = certRequest;
+        }
+
+        /**
+         * Get the opaque message data
+         */
+        public byte[] getData() {
+            return mCertRequest.getData();
+        }
+
+        /**
+         * Get the default URL to use when sending the certificate request
+         * message to a server, if known. The app may prefer to use a different
+         * certificate server URL obtained from other sources.
+         */
+        public String getDefaultUrl() {
+            return mCertRequest.getDefaultUrl();
+        }
+    }
+
+    /**
+     * Contains the wrapped private key and public certificate data associated
+     * with a certificate.
+     */
+    public final static class Certificate {
+        private final MediaDrm.Certificate mCertificate;
+
+        Certificate(MediaDrm.Certificate certificate) {
+            mCertificate = certificate;
+        }
+
+        /**
+         * Get the wrapped private key data
+         */
+        public byte[] getWrappedPrivateKey() {
+            return mCertificate.getWrappedPrivateKey();
+        }
+
+        /**
+         * Get the PEM-encoded public certificate chain
+         */
+        public byte[] getContent() {
+            return mCertificate.getContent();
+        }
+    }
+
+    /**
+     * Generate a certificate request, specifying the certificate type
+     * and authority. The response received should be passed to
+     * provideCertificateResponse.
+     *
+     * @param drm the MediaDrm object
+     * @param certType Specifies the certificate type.
+     * @param certAuthority is passed to the certificate server to specify
+     * the chain of authority.
+     */
+    public static CertificateRequest getCertificateRequest(MediaDrm drm, int certType,
+            String certAuthority) {
+        return new CertificateRequest(drm.getCertificateRequest(certType, certAuthority));
+    }
+
+    /**
+     * Process a response from the provisioning server.  The response
+     * is obtained from an HTTP Post to the url provided by getCertificateRequest.
+     *
+     * The public X509 certificate chain and wrapped private key are returned
+     * in the returned Certificate objec.  The certificate chain is in BIO serialized
+     * PEM format.  The wrapped private key should be stored in application private
+     * storage, and used when invoking the signRSA method.
+     *
+     * @param drm the MediaDrm object
+     * @param response the opaque certificate response byte array to provide to the
+     * DRM engine plugin.
+     * @throws android.media.DeniedByServerException if the response indicates that the
+     * server rejected the request
+     */
+    public static Certificate provideCertificateResponse(MediaDrm drm, byte[] response)
+            throws DeniedByServerException {
+        return new Certificate(drm.provideCertificateResponse(response));
+    }
+
+    /**
+     * Sign data using an RSA key
+     *
+     * @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"
+     * @param wrappedKey - the wrapped (encrypted) RSA private key obtained
+     * from provideCertificateResponse
+     * @param message the data for which a signature is to be computed
+     */
+    public static byte[] signRSA(MediaDrm drm, byte[] sessionId,
+            String algorithm, byte[] wrappedKey, byte[] message) {
+        return drm.signRSA(sessionId, algorithm, wrappedKey, message);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 43ebef4..5f3ba74 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -140,7 +140,9 @@
 
     private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
         int requestId = mCameraUser.submitRequest(request, streaming);
-        assertTrue("Request IDs should be non-negative", requestId >= 0);
+        assertTrue(
+                "Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")",
+                requestId >= 0);
         return requestId;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
index 3f17aa9..26498ca 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -309,7 +309,7 @@
                 });
 
         // rational (n) -- in particular rational x 9
-        checkKeyGetAndSetArray("android.sensor.calibrationTransform1", Rational[].class,
+        checkKeyGetAndSetArray("android.sensor.calibrationTransform", Rational[].class,
                 new Rational[] {
                         new Rational(1, 2), new Rational(3, 4), new Rational(5, 6),
                         new Rational(7, 8), new Rational(9, 10), new Rational(10, 11),
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/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
index c3aa47f..354d13f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
@@ -981,6 +981,13 @@
             return;
         }
 
+        if (mLockPatternUtils.checkVoldPassword()) {
+            if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
+            // Without this, settings is not enabled until the lock screen first appears
+            hideLocked();
+            return;
+        }
+
         if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
         showLocked(options);
     }
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 f6e875c..96da21f 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -26,23 +26,31 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="top|center_horizontal"
-        android:background="#88000000">
+        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 a9b69854..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>
@@ -248,6 +251,6 @@
     <!-- Z distance between notifications if they are in the stack -->
     <dimen name="z_distance_between_notifications">2dp</dimen>
 
-    <!-- Width of the zen mode interstitial dialog.  Defaults to MATCH_PARENT. -->
-    <dimen name="zen_mode_dialog_width">-1px</dimen>
+    <!-- Width of the zen mode interstitial dialog. -->
+    <dimen name="zen_mode_dialog_width">320dp</dimen>
 </resources>
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/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 9d2d6ee..ab2ad96 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -368,7 +368,7 @@
         final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
 
         final List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasksForUser(1,
-                ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
+                ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_PROFILES,
                 UserHandle.CURRENT.getIdentifier());
         TaskDescription item = null;
         if (recentTasks.size() > 0) {
@@ -441,7 +441,7 @@
 
                 final List<ActivityManager.RecentTaskInfo> recentTasks =
                         am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE
-                        | ActivityManager.RECENT_INCLUDE_RELATED);
+                        | ActivityManager.RECENT_INCLUDE_PROFILES);
                 int numTasks = recentTasks.size();
                 ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN)
                         .addCategory(Intent.CATEGORY_HOME).resolveActivityInfo(pm, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
index f75ea92..7ab40b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
@@ -165,7 +165,7 @@
                     am.getRecentTasks(2,
                             ActivityManager.RECENT_WITH_EXCLUDED |
                             ActivityManager.RECENT_IGNORE_UNAVAILABLE |
-                            ActivityManager.RECENT_INCLUDE_RELATED);
+                            ActivityManager.RECENT_INCLUDE_PROFILES);
             if (recentTasks.size() > 1 &&
                     mRecentsPanel.simulateClick(recentTasks.get(1).persistentId)) {
                 // recents panel will take care of calling show(false) through simulateClick
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 1a616a0..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_RELATED,
+        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_RELATED,
+        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 b5950e9..8c5c8fa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -26,11 +26,17 @@
         public static final boolean Verbose = false;
 
         public static class App {
-            public static final boolean EnableTaskFiltering = false;
+            public static final boolean EnableTaskFiltering = true;
             public static final boolean EnableTaskStackClipping = false;
             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,14 +79,16 @@
         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 {
             public static class Animation {
                 public static final int TaskRemovedReshuffleDuration = 200;
                 public static final int SnapScrollBackDuration = 650;
+                public static final int FilteredCurrentViewsDuration = 150;
+                public static final int FilteredNewViewsDuration = 200;
+                public static final int UnfilteredCurrentViewsDuration = 150;
+                public static final int UnfilteredNewViewsDuration = 200;
             }
 
             public static final int TaskStackOverscrollRange = 150;
@@ -107,7 +115,7 @@
             public static final boolean AnimateFrontTaskIconOnEnterRecents = true;
             public static final boolean AnimateFrontTaskIconOnLeavingRecents = true;
 
-            public static final boolean UseRoundedCorners = true;
+            public static final boolean UseRoundedCorners = false;
             public static final float RoundedCornerRadiusDps = 3;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index b65b864..dd75921 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -54,8 +54,11 @@
                     finish();
                 }
             } else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
-                // Dismiss recents and launch the first task if possible
-                dismissRecentsIfVisible();
+                // Try and unfilter and filtered stacks
+                if (!mRecentsView.unfilterFilteredStacks()) {
+                    // If there are no filtered stacks, dismiss recents and launch the first task
+                    dismissRecentsIfVisible();
+                }
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 515cec1..22363bb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -66,7 +66,7 @@
                 // in a bottom inset
                 tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top, 0);
                 tsv.boundScroll();
-                TaskViewTransform transform = tsv.getStackTransform(0);
+                TaskViewTransform transform = tsv.getStackTransform(0, tsv.getStackScroll());
                 Rect taskRect = new Rect(transform.rect);
 
                 data.putParcelable("taskRect", taskRect);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index b497b69..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.intent.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.intent.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_RELATED, 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/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 33e4246..9048cba 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -20,9 +20,6 @@
 
 /* Common code */
 public class Utilities {
-    public static final Rect tmpRect = new Rect();
-    public static final Rect tmpRect2 = new Rect();
-
     /** Scales a rect about its centroid */
     public static void scaleRectAboutCenter(Rect r, float scale) {
         if (scale != 1.0f) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index cda4ab2..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;
 
 
 /**
@@ -37,11 +36,11 @@
     /* The Task Key represents the unique primary key for the task */
     public static class TaskKey {
         public final int id;
-        public final Intent intent;
+        public final Intent baseIntent;
 
         public TaskKey(int id, Intent intent) {
             this.id = id;
-            this.intent = intent;
+            this.baseIntent = intent;
         }
 
         @Override
@@ -56,28 +55,24 @@
 
         @Override
         public String toString() {
-            return "Task.Key: " + id + ", " + intent.getComponent().getPackageName();
+            return "Task.Key: " + id + ", " + baseIntent.getComponent().getPackageName();
         }
     }
 
     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,20 +102,13 @@
 
     @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);
     }
 
     @Override
     public String toString() {
-        return "Task: " + key.intent.getComponent().getPackageName() + " [" + super.toString() + "]";
+        return "Task: " + key.baseIntent.getComponent().getPackageName() + " [" + super.toString() + "]";
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index f2f89ae..a0e5b6a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -39,9 +39,11 @@
     TaskFilter mFilter;
 
     /** Sets the task filter, saving the current touch state */
-    void setFilter(TaskFilter filter) {
+    boolean setFilter(TaskFilter filter) {
+        ArrayList<Task> prevFilteredTasks = new ArrayList<Task>(mFilteredTasks);
         mFilter = filter;
         updateFilteredTasks();
+        return !prevFilteredTasks.equals(mFilteredTasks);
     }
 
     /** Removes the task filter and returns the previous touch state */
@@ -126,9 +128,9 @@
         /* Notifies when a task has been removed from the stack */
         public void onStackTaskRemoved(TaskStack stack, Task t);
         /** Notifies when the stack was filtered */
-        public void onStackFiltered(TaskStack stack);
+        public void onStackFiltered(TaskStack newStack, ArrayList<Task> curStack, Task t);
         /** Notifies when the stack was un-filtered */
-        public void onStackUnfiltered(TaskStack stack);
+        public void onStackUnfiltered(TaskStack newStack, ArrayList<Task> curStack);
     }
 
     Context mContext;
@@ -201,29 +203,30 @@
     }
 
     /** Filters the stack into tasks similar to the one specified */
-    public void filterTasks(Task t) {
+    public void filterTasks(final Task t) {
+        ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks());
+
         // Set the task list filter
-        // XXX: This is a dummy filter that currently just accepts every other task.
-        mTaskList.setFilter(new TaskFilter() {
+        boolean filtered = mTaskList.setFilter(new TaskFilter() {
             @Override
-            public boolean acceptTask(Task t, int i) {
-                if (i % 2 == 0) {
-                    return true;
-                }
-                return false;
+            public boolean acceptTask(Task at, int i) {
+                return t.key.baseIntent.getComponent().getPackageName().equals(
+                        at.key.baseIntent.getComponent().getPackageName());
             }
         });
-        if (mCb != null) {
-            mCb.onStackFiltered(this);
+        if (filtered && mCb != null) {
+            mCb.onStackFiltered(this, oldStack, t);
         }
     }
 
     /** Unfilters the current stack */
     public void unfilterTasks() {
+        ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks());
+
         // Unset the filter, then update the virtual scroll
         mTaskList.removeFilter();
         if (mCb != null) {
-            mCb.onStackUnfiltered(this);
+            mCb.onStackUnfiltered(this, oldStack);
         }
     }
 
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 cc85439..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;
@@ -211,17 +211,18 @@
                 View sourceView = tv;
                 int offsetX = 0;
                 int offsetY = 0;
+                int stackScroll = stackView.getStackScroll();
                 if (tv == null) {
                     // If there is no actual task view, then use the stack view as the source view
                     // and then offset to the expected transform rect, but bound this to just
                     // outside the display rect (to ensure we don't animate from too far away)
                     RecentsConfiguration config = RecentsConfiguration.getInstance();
                     sourceView = stackView;
-                    transform = stackView.getStackTransform(stack.indexOfTask(task));
+                    transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
                     offsetX = transform.rect.left;
                     offsetY = Math.min(transform.rect.top, config.displayRect.height());
                 } else {
-                    transform = stackView.getStackTransform(stack.indexOfTask(task));
+                    transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
                 }
 
                 // Compute the thumbnail to scale up from
@@ -245,17 +246,11 @@
 
                 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.intent);
+                    Intent i = new Intent(task.key.baseIntent);
                     i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
                             | Intent.FLAG_ACTIVITY_TASK_ON_HOME
                             | Intent.FLAG_ACTIVITY_NEW_TASK);
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 e7f517f..dfd608c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -18,10 +18,10 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
 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;
@@ -34,14 +34,15 @@
 import android.view.ViewParent;
 import android.widget.FrameLayout;
 import android.widget.OverScroller;
+import com.android.systemui.R;
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.RecentsTaskLoader;
+import com.android.systemui.recents.SystemServicesProxy;
 import com.android.systemui.recents.Utilities;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.R;
 
 import java.util.ArrayList;
 
@@ -71,6 +72,7 @@
     int mStackScroll;
     int mMinScroll;
     int mMaxScroll;
+    int mStashedScroll;
     OverScroller mScroller;
     ObjectAnimator mScrollAnimator;
 
@@ -79,6 +81,9 @@
     int mStackViewsAnimationDuration;
     boolean mStackViewsDirty = true;
     boolean mAwaitingFirstLayout = true;
+    int[] mTmpVisibleRange = new int[2];
+    Rect mTmpRect = new Rect();
+    Rect mTmpRect2 = new Rect();
     LayoutInflater mInflater;
 
     public TaskStackView(Context context, TaskStack stack) {
@@ -102,7 +107,7 @@
     }
     void requestSynchronizeStackViewsWithModel(int duration) {
         Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
-                "[TaskStackView|requestSynchronize]", "", Console.AnsiYellow);
+                "[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
         if (!mStackViewsDirty) {
             invalidate();
         }
@@ -128,14 +133,17 @@
     }
 
     /** Update/get the transform */
-    public TaskViewTransform getStackTransform(int indexInStack) {
+    public TaskViewTransform getStackTransform(int indexInStack, int stackScroll) {
         TaskViewTransform transform = new TaskViewTransform();
 
-        // Map the items to an continuous position relative to the current scroll
+        // Return early if we have an invalid index
+        if (indexInStack < 0) return transform;
+
+        // Map the items to an continuous position relative to the specified scroll
         int numPeekCards = Constants.Values.TaskStackView.StackPeekNumCards;
         float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
         float peekHeight = Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
-        float t = ((indexInStack * overlapHeight) - getStackScroll()) / overlapHeight;
+        float t = ((indexInStack * overlapHeight) - stackScroll) / overlapHeight;
         float boundedT = Math.max(t, -(numPeekCards + 1));
 
         // Set the scale relative to its position
@@ -167,25 +175,57 @@
         return transform;
     }
 
+    /**
+     * Gets the stack transforms of a list of tasks, and returns the visible range of tasks.
+     */
+    private ArrayList<TaskViewTransform> getStackTransforms(ArrayList<Task> tasks,
+                                                            int stackScroll,
+                                                            int[] visibleRangeOut) {
+        // XXX: Optimization: Use binary search to find the visible range
+
+        ArrayList<TaskViewTransform> taskTransforms = new ArrayList<TaskViewTransform>();
+        int taskCount = tasks.size();
+        int firstVisibleIndex = -1;
+        int lastVisibleIndex = -1;
+        for (int i = 0; i < taskCount; i++) {
+            TaskViewTransform transform = getStackTransform(i, stackScroll);
+            taskTransforms.add(transform);
+            if (transform.visible) {
+                if (firstVisibleIndex < 0) {
+                    firstVisibleIndex = i;
+                }
+                lastVisibleIndex = i;
+            }
+        }
+        if (visibleRangeOut != null) {
+            visibleRangeOut[0] = firstVisibleIndex;
+            visibleRangeOut[1] = lastVisibleIndex;
+        }
+        return taskTransforms;
+    }
+
     /** Synchronizes the views with the model */
     void synchronizeStackViewsWithModel() {
         Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
                 "[TaskStackView|synchronizeViewsWithModel]",
                 "mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
         if (mStackViewsDirty) {
-
-            // XXX: Optimization: Use binary search to find the visible range
-            // XXX: Optimize to not call getStackTransform() so many times
             // XXX: Consider using TaskViewTransform pool to prevent allocations
             // XXX: Iterate children views, update transforms and remove all that are not visible
             //      For all remaining tasks, update transforms and if visible add the view
 
-            // Update the visible state of all the tasks
+            // Get all the task transforms
+            int[] visibleRange = mTmpVisibleRange;
+            int stackScroll = getStackScroll();
             ArrayList<Task> tasks = mStack.getTasks();
+            ArrayList<TaskViewTransform> taskTransforms = getStackTransforms(tasks, stackScroll,
+                    visibleRange);
+
+            // Update the visible state of all the tasks
             int taskCount = tasks.size();
             for (int i = 0; i < taskCount; i++) {
                 Task task = tasks.get(i);
-                TaskViewTransform transform = getStackTransform(i);
+                TaskViewTransform transform = taskTransforms.get(i);
                 TaskView tv = getChildViewForTask(task);
 
                 if (transform.visible) {
@@ -194,11 +234,10 @@
                         // 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) {
-                            // XXX: We have to animate when filtering, etc. Maybe we should have a
-                            //      runnable that ensures that tasks are animated in a special way
-                            //      when they are entering the scene?
-                            int fromIndex = (transform.t < 0) ? (i - 1) : (i + 1);
-                            tv.updateViewPropertiesFromTask(null, getStackTransform(fromIndex), 0);
+                            int fromIndex = (transform.t < 0) ? (visibleRange[0] - 1) :
+                                    (visibleRange[1] + 1);
+                            tv.updateViewPropertiesToTaskTransform(null,
+                                    getStackTransform(fromIndex, stackScroll), 0);
                         }
                     }
                 } else {
@@ -208,17 +247,18 @@
                 }
             }
 
-            // Update all the current view children
+            // Update all the remaining view children
             // NOTE: We have to iterate in reverse where because we are removing views directly
             int childCount = getChildCount();
             for (int i = childCount - 1; i >= 0; i--) {
                 TaskView tv = (TaskView) getChildAt(i);
                 Task task = tv.getTask();
-                TaskViewTransform transform = getStackTransform(mStack.indexOfTask(task));
-                if (!transform.visible) {
+                int taskIndex = mStack.indexOfTask(task);
+                if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
                     mViewPool.returnViewToPool(tv);
                 } else {
-                    tv.updateViewPropertiesFromTask(null, transform, mStackViewsAnimationDuration);
+                    tv.updateViewPropertiesToTaskTransform(null, taskTransforms.get(taskIndex),
+                            mStackViewsAnimationDuration);
                 }
             }
 
@@ -235,6 +275,10 @@
         mStackScroll = value;
         requestSynchronizeStackViewsWithModel();
     }
+    /** Sets the current stack scroll without synchronizing the stack view with the model */
+    public void setStackScrollRaw(int value) {
+        mStackScroll = value;
+    }
 
     /** Gets the current stack scroll */
     public int getStackScroll() {
@@ -251,36 +295,39 @@
 
             // Abort any current animations
             abortScroller();
-            if (mScrollAnimator != null) {
-                mScrollAnimator.cancel();
-                mScrollAnimator.removeAllListeners();
-            }
+            abortBoundScrollAnimation();
 
             // Start a new scroll animation
-            mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
-            mScrollAnimator.setDuration(duration);
-            mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    setStackScroll((Integer) animation.getAnimatedValue());
-                }
-            });
-            mScrollAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    // Disable hw layers on the stack
-                    decHwLayersRefCount("animateBoundScroll");
-                }
-            });
+            animateScroll(curScroll, newScroll, duration);
             mScrollAnimator.start();
         }
         return mScrollAnimator;
     }
 
+    /** Animates the stack scroll */
+    void animateScroll(int curScroll, int newScroll, int duration) {
+        mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
+        mScrollAnimator.setDuration(duration);
+        mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                setStackScroll((Integer) animation.getAnimatedValue());
+            }
+        });
+        mScrollAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                // Disable hw layers on the stack
+                decHwLayersRefCount("animateBoundScroll");
+            }
+        });
+    }
+
     /** Aborts any current stack scrolls */
     void abortBoundScrollAnimation() {
         if (mScrollAnimator != null) {
             mScrollAnimator.cancel();
+            mScrollAnimator.removeAllListeners();
         }
     }
 
@@ -304,6 +351,20 @@
         return false;
     }
 
+    /**
+     * Bounds the current scroll if necessary, but does not synchronize the stack view with the
+     * model.
+     */
+    public boolean boundScrollRaw() {
+        int curScroll = getStackScroll();
+        int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
+        if (newScroll != curScroll) {
+            setStackScrollRaw(newScroll);
+            return true;
+        }
+        return false;
+    }
+
     /** Returns whether the current scroll is out of bounds */
     boolean isScrollOutOfBounds() {
         return (getStackScroll() < 0) || (getStackScroll() > mMaxScroll);
@@ -404,12 +465,12 @@
             TaskView tv = (TaskView) child;
             TaskView nextTv = null;
             int curIndex = indexOfChild(tv);
-            if (curIndex < (getChildCount() - 1)) {
+            if ((curIndex > -1) && (curIndex < (getChildCount() - 1))) {
                 // Clip against the next view (if we aren't animating its alpha)
                 nextTv = (TaskView) getChildAt(curIndex + 1);
                 if (nextTv.getAlpha() == 1f) {
-                    Rect curRect = tv.getClippingRect(Utilities.tmpRect, false);
-                    Rect nextRect = nextTv.getClippingRect(Utilities.tmpRect2, true);
+                    Rect curRect = tv.getClippingRect(mTmpRect, false);
+                    Rect nextRect = nextTv.getClippingRect(mTmpRect2, true);
                     RecentsConfiguration config = RecentsConfiguration.getInstance();
                     // The hit rects are relative to the task view, which needs to be offset by the
                     // system bar height
@@ -528,9 +589,7 @@
                     mTaskRect.right, mStackRectSansPeek.top + mTaskRect.height());
         }
 
-        if (!mAwaitingFirstLayout) {
-            requestSynchronizeStackViewsWithModel();
-        } else {
+        if (mAwaitingFirstLayout) {
             mAwaitingFirstLayout = false;
         }
     }
@@ -570,13 +629,185 @@
     }
 
     @Override
-    public void onStackFiltered(TaskStack stack) {
-        requestSynchronizeStackViewsWithModel();
+    public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curStack,
+                                Task filteredTask) {
+        // NOTE: This code assumes that the current (unfiltered) stack is a superset of the new
+        // (filtered) stack
+        // XXX: Use HW Layers
+
+        // Stash the scroll for us to restore to when we unfilter
+        mStashedScroll = getStackScroll();
+
+        // Compute the transforms of the items in the current stack
+        final ArrayList<TaskViewTransform> curTaskTransforms =
+                getStackTransforms(curStack, mStashedScroll, null);
+
+        // Bound the new stack scroll
+        updateMinMaxScroll(false);
+        boundScrollRaw();
+
+        // Compute the transforms of the items in the new stack
+        final ArrayList<TaskViewTransform> taskTransforms =
+                getStackTransforms(mStack.getTasks(), getStackScroll(), null);
+
+        // Animate all of the existing views on screen either out of view (if they are not visible
+        // in the new stack) or to their final positions in the new stack
+        final ArrayList<TaskView> childrenToReturnToPool = new ArrayList<TaskView>();
+        final ArrayList<Task> tasks = mStack.getTasks();
+        ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            TaskView tv = (TaskView) getChildAt(i);
+            Task task = tv.getTask();
+            TaskViewTransform toTransform;
+            int taskIndex = tasks.indexOf(task);
+            if ((taskIndex < 0) || !taskTransforms.get(taskIndex).visible) {
+                // Compose a new transform that animates the task view out of view
+                TaskViewTransform fromTransform = curTaskTransforms.get(curStack.indexOf(task));
+                toTransform = new TaskViewTransform(fromTransform);
+                tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
+                tv.prepareTaskTransformForFilterTaskHidden(toTransform);
+
+                childrenToReturnToPool.add(tv);
+            } else {
+                toTransform = taskTransforms.get(taskIndex);
+            }
+            childViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
+        }
+
+        AnimatorSet childViewAnimSet = new AnimatorSet();
+        childViewAnimSet.setDuration(
+                Constants.Values.TaskStackView.Animation.FilteredCurrentViewsDuration);
+        childViewAnimSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                // Return all the removed children to the view pool
+                for (TaskView tv : childrenToReturnToPool) {
+                    mViewPool.returnViewToPool(tv);
+                }
+
+                // For views that are not already visible, animate them in
+                int taskCount = tasks.size();
+                for (int i = 0; i < taskCount; i++) {
+                    Task task = tasks.get(i);
+                    TaskViewTransform toTransform = taskTransforms.get(i);
+                    if (toTransform.visible) {
+                        TaskViewTransform fromTransform =
+                                curTaskTransforms.get(curStack.indexOf(task));
+                        TaskView tv = getChildViewForTask(task);
+                        if (tv == null) {
+                            tv = mViewPool.pickUpViewFromPool(task, task);
+
+                            // Animate from the current position to the new position
+                            tv.prepareTaskTransformForFilterTaskVisible(fromTransform);
+                            tv.updateViewPropertiesToTaskTransform(fromTransform,
+                                    toTransform,
+                                    Constants.Values.TaskStackView.Animation.FilteredNewViewsDuration);
+                        }
+                    }
+                }
+                invalidate();
+            }
+        });
+        childViewAnimSet.playTogether(childViewAnims);
+        childViewAnimSet.start();
     }
 
     @Override
-    public void onStackUnfiltered(TaskStack stack) {
-        requestSynchronizeStackViewsWithModel();
+    public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curStack) {
+        // Compute the transforms of the items in the current stack
+        final int curScroll = getStackScroll();
+        final ArrayList<TaskViewTransform> curTaskTransforms =
+                getStackTransforms(curStack, curScroll, null);
+
+        // Restore the stashed scroll
+        updateMinMaxScroll(false);
+        setStackScrollRaw(mStashedScroll);
+        boundScrollRaw();
+
+        // Compute the transforms of the items in the new stack
+        final ArrayList<TaskViewTransform> taskTransforms =
+                getStackTransforms(mStack.getTasks(), getStackScroll(), null);
+
+        // Animate all of the existing views out of view (if they are not in the visible range in
+        // the new stack) or to their final positions in the new stack
+        final ArrayList<TaskView> childrenToRemove = new ArrayList<TaskView>();
+        final ArrayList<Task> tasks = mStack.getTasks();
+        ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            TaskView tv = (TaskView) getChildAt(i);
+            Task task = tv.getTask();
+            int taskIndex = tasks.indexOf(task);
+            TaskViewTransform transform;
+
+            // If the view is no longer visible, then we should just animate it out
+            if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
+                transform = new TaskViewTransform(curTaskTransforms.get(curStack.indexOf(task)));
+                tv.prepareTaskTransformForFilterTaskVisible(transform);
+                childrenToRemove.add(tv);
+            } else {
+                transform = taskTransforms.get(taskIndex);
+            }
+            childViewAnims.add(tv.getAnimatorToTaskTransform(transform));
+        }
+
+        AnimatorSet childViewAnimSet = new AnimatorSet();
+        childViewAnimSet.setDuration(
+                Constants.Values.TaskStackView.Animation.UnfilteredCurrentViewsDuration);
+        childViewAnimSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                // Return all the removed children to the view pool
+                for (TaskView tv : childrenToRemove) {
+                    mViewPool.returnViewToPool(tv);
+                }
+
+                // Increment the hw layers ref count
+                addHwLayersRefCount("unfilteredNewViews");
+
+                // For views that are not already visible, animate them in
+                ArrayList<Animator> newViewAnims = new ArrayList<Animator>();
+                AnimatorSet newViewAnimSet = new AnimatorSet();
+                int taskCount = tasks.size();
+                int offset = 0;
+                for (int i = 0; i < taskCount; i++) {
+                    Task task = tasks.get(i);
+                    TaskViewTransform toTransform = taskTransforms.get(i);
+                    if (toTransform.visible) {
+                        TaskView tv = getChildViewForTask(task);
+                        if (tv == null) {
+                            // For views that are not already visible, animate them in
+                            tv = mViewPool.pickUpViewFromPool(task, task);
+
+                            // Animate in this new view
+                            TaskViewTransform fromTransform = new TaskViewTransform(toTransform);
+                            tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
+                            tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
+                            newViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
+                            offset++;
+                        }
+                    }
+                }
+
+                // Run the animation
+                newViewAnimSet.setDuration(
+                        Constants.Values.TaskStackView.Animation.UnfilteredNewViewsDuration);
+                newViewAnimSet.playTogether(newViewAnims);
+                newViewAnimSet.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        // Decrement the hw layers ref count
+                        decHwLayersRefCount("unfilteredNewViews");
+                    }
+                });
+                newViewAnimSet.start();
+
+                invalidate();
+            }
+        });
+        childViewAnimSet.playTogether(childViewAnims);
+        childViewAnimSet.start();
     }
 
     /**** ViewPoolConsumer Implementation ****/
@@ -845,7 +1076,7 @@
 
     /** Handles touch events once we have intercepted them */
     public boolean onTouchEvent(MotionEvent ev) {
-        Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
+        Console.log(Constants.DebugFlags.UI.TouchEvents,
                 "[TaskStackViewTouchHandler|touchEvent]",
                 Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
 
@@ -1038,16 +1269,19 @@
         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 just close the activity
+        // If there are no remaining tasks, then either unfilter the current stack, or just close
+        // the activity if there are no filtered stacks
         if (mSv.mStack.getTaskCount() == 0) {
-            activity.finish();
+            boolean shouldFinishActivity = true;
+            if (mSv.mStack.hasFilteredTasks()) {
+                mSv.mStack.unfilterTasks();
+                shouldFinishActivity = (mSv.mStack.getTaskCount() == 0);
+            }
+            if (shouldFinishActivity) {
+                activity.finish();
+            }
         }
 
         // Disable HW layers
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 c86b0e1..2c27d44 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.recents.views;
 
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Path;
@@ -72,6 +75,7 @@
         // Bind the views
         mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
         mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
+        mBarView.mApplicationIcon.setOnClickListener(this);
         if (mTaskDataLoaded) {
             onTaskDataLoaded(false);
         }
@@ -90,12 +94,16 @@
     }
 
     @Override
-    protected void onDraw(Canvas canvas) {
+    protected void dispatchDraw(Canvas canvas) {
+        int restoreCount = 0;
         if (Constants.Values.TaskView.UseRoundedCorners) {
+            restoreCount = canvas.save();
             canvas.clipPath(mRoundedRectClipPath);
         }
-
-        super.onDraw(canvas);
+        super.dispatchDraw(canvas);
+        if (Constants.Values.TaskView.UseRoundedCorners) {
+            canvas.restoreToCount(restoreCount);
+        }
     }
 
     /** Set callback */
@@ -109,27 +117,43 @@
     }
 
     /** Synchronizes this view's properties with the task's transform */
-    void updateViewPropertiesFromTask(TaskViewTransform animateFromTransform,
-                                      TaskViewTransform transform, int duration) {
+    void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
+                                             TaskViewTransform toTransform, int duration) {
         if (duration > 0) {
             if (animateFromTransform != null) {
                 setTranslationY(animateFromTransform.translationY);
                 setScaleX(animateFromTransform.scale);
                 setScaleY(animateFromTransform.scale);
+                setAlpha(animateFromTransform.alpha);
             }
-            animate().translationY(transform.translationY)
-                    .scaleX(transform.scale)
-                    .scaleY(transform.scale)
+            animate().translationY(toTransform.translationY)
+                    .scaleX(toTransform.scale)
+                    .scaleY(toTransform.scale)
+                    .alpha(toTransform.alpha)
                     .setDuration(duration)
                     .setInterpolator(new AccelerateDecelerateInterpolator())
+                    .withLayer()
                     .start();
         } else {
-            setTranslationY(transform.translationY);
-            setScaleX(transform.scale);
-            setScaleY(transform.scale);
+            setTranslationY(toTransform.translationY);
+            setScaleX(toTransform.scale);
+            setScaleY(toTransform.scale);
+            setAlpha(toTransform.alpha);
         }
     }
 
+    /** Returns an animator to animate this task to the specified transform */
+    Animator getAnimatorToTaskTransform(TaskViewTransform toTransform) {
+        AnimatorSet anims = new AnimatorSet();
+        anims.playTogether(
+                ObjectAnimator.ofFloat(this, "translationY", toTransform.translationY),
+                ObjectAnimator.ofFloat(this, "scaleX", toTransform.scale),
+                ObjectAnimator.ofFloat(this, "scaleY", toTransform.scale),
+                ObjectAnimator.ofFloat(this, "alpha", toTransform.alpha)
+        );
+        return anims;
+    }
+
     /** Resets this view's properties */
     void resetViewProperties() {
         setTranslationX(0f);
@@ -139,6 +163,17 @@
         setAlpha(1f);
     }
 
+    void prepareTaskTransformForFilterTaskHidden(TaskViewTransform toTransform) {
+        // Fade the view out and slide it away
+        toTransform.alpha = 0f;
+        toTransform.translationY += 200;
+    }
+
+    void prepareTaskTransformForFilterTaskVisible(TaskViewTransform fromTransform) {
+        // Fade the view in
+        fromTransform.alpha = 0f;
+    }
+
     /** Animates this task view as it enters recents */
     public void animateOnEnterRecents() {
         RecentsConfiguration config = RecentsConfiguration.getInstance();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index 66c52a0..0748bbb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -23,13 +23,27 @@
 public class TaskViewTransform {
     public int translationY = 0;
     public float scale = 1f;
-    public boolean visible = true;
+    public float alpha = 1f;
+    public boolean visible = false;
     public Rect rect = new Rect();
     float t;
 
+    public TaskViewTransform() {
+        // Do nothing
+    }
+
+    public TaskViewTransform(TaskViewTransform o) {
+        translationY = o.translationY;
+        scale = o.scale;
+        alpha = o.alpha;
+        visible = o.visible;
+        rect.set(o.rect);
+        t = o.t;
+    }
+
     @Override
     public String toString() {
-        return "TaskViewTransform y: " + translationY + " scale: " + scale +
+        return "TaskViewTransform y: " + translationY + " scale: " + scale + " alpha: " + alpha +
                 " visible: " + visible + " rect: " + rect;
     }
 }
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 bad5641..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;
@@ -134,7 +132,7 @@
     protected PopupMenu mNotificationBlamePopup;
 
     protected int mCurrentUserId = 0;
-    final protected SparseArray<UserInfo> mRelatedUsers = new SparseArray<UserInfo>();
+    final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
 
     protected int mLayoutDirection = -1; // invalid
     private Locale mLocale;
@@ -244,21 +242,21 @@
             String action = intent.getAction();
             if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                 mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
-                updateRelatedUserCache();
+                updateCurrentProfilesCache();
                 if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
                 userSwitched(mCurrentUserId);
             } else if (Intent.ACTION_USER_ADDED.equals(action)) {
-                updateRelatedUserCache();
+                updateCurrentProfilesCache();
             }
         }
     };
 
-    private void updateRelatedUserCache() {
-        synchronized (mRelatedUsers) {
-            mRelatedUsers.clear();
+    private void updateCurrentProfilesCache() {
+        synchronized (mCurrentProfiles) {
+            mCurrentProfiles.clear();
             if (mUserManager != null) {
-                for (UserInfo related : mUserManager.getRelatedUsers(mCurrentUserId)) {
-                    mRelatedUsers.put(related.id, related);
+                for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
+                    mCurrentProfiles.put(user.id, user);
                 }
             }
         }
@@ -361,24 +359,23 @@
         filter.addAction(Intent.ACTION_USER_ADDED);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
-        updateRelatedUserCache();
+        updateCurrentProfilesCache();
     }
 
     public void userSwitched(int newUserId) {
         // should be overridden
     }
 
-    public boolean notificationIsForCurrentOrRelatedUser(StatusBarNotification n) {
+    public boolean notificationIsForCurrentProfiles(StatusBarNotification n) {
         final int thisUserId = mCurrentUserId;
         final int notificationUserId = n.getUserId();
         if (DEBUG && MULTIUSER_DEBUG) {
             Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
                     n, thisUserId, notificationUserId));
         }
-        synchronized (mRelatedUsers) {
+        synchronized (mCurrentProfiles) {
             return notificationUserId == UserHandle.USER_ALL
-                    || thisUserId == notificationUserId
-                    || mRelatedUsers.get(notificationUserId) != null;
+                    || mCurrentProfiles.get(notificationUserId) != null;
         }
     }
 
@@ -1034,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;
@@ -1258,7 +1255,7 @@
         updateNotificationVetoButton(oldEntry.row, notification);
 
         // Is this for you?
-        boolean isForCurrentUser = notificationIsForCurrentOrRelatedUser(notification);
+        boolean isForCurrentUser = notificationIsForCurrentProfiles(notification);
         if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
 
         // Restart the ticker if it's still running
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 e7f96dc..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();
 
@@ -1078,8 +1061,8 @@
             Entry ent = mNotificationData.get(N-i-1);
             if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
 
-            // TODO How do we want to badge notifcations from related users.
-            if (!notificationIsForCurrentOrRelatedUser(ent.notification)) continue;
+            // TODO How do we want to badge notifcations from profiles.
+            if (!notificationIsForCurrentProfiles(ent.notification)) continue;
 
             final int vis = ent.notification.getNotification().visibility;
             if (vis != Notification.VISIBILITY_SECRET) {
@@ -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);
             }
         }
 
@@ -1138,7 +1121,7 @@
             Entry ent = mNotificationData.get(N-i-1);
             if (!((provisioned && ent.notification.getScore() >= HIDE_ICONS_BELOW_SCORE)
                     || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
-            if (!notificationIsForCurrentOrRelatedUser(ent.notification)) continue;
+            if (!notificationIsForCurrentProfiles(ent.notification)) continue;
             if (isLockscreenPublicMode()
                     && ent.notification.getNotification().visibility
                             == Notification.VISIBILITY_SECRET
@@ -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) {
@@ -2150,7 +2098,7 @@
         if (!isDeviceProvisioned()) return;
 
         // not for you
-        if (!notificationIsForCurrentOrRelatedUser(n)) return;
+        if (!notificationIsForCurrentProfiles(n)) return;
 
         // Show the ticker if one is requested. Also don't do this
         // until status bar window is attached to the window manager,
@@ -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/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index aed9a71..d67f7cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -911,6 +911,7 @@
                 d.getWindow().setAttributes(lp);
             }
         };
+        v.setAutoActivate(true);
         v.setAdapter(new ZenModeViewAdapter(mContext) {
             @Override
             public void configure() {
@@ -928,7 +929,6 @@
         d.create();
         d.getWindow().setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
         WindowManager.LayoutParams lp = d.getWindow().getAttributes();
-        lp.horizontalMargin = 0;
         lp.width = mContext.getResources().getDimensionPixelSize(R.dimen.zen_mode_dialog_width);
         d.getWindow().setAttributes(lp);
         d.show();
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/phone/ZenModeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
index d1a9d57..49cf78b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -16,11 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.content.Context;
-import android.graphics.Paint;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.Typeface;
 import android.graphics.drawable.ShapeDrawable;
@@ -39,14 +36,12 @@
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.FrameLayout;
-import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 import android.widget.Switch;
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.ZenModeView.Adapter.ExitCondition;
 
 public class ZenModeView extends RelativeLayout {
@@ -63,20 +58,21 @@
 
     private static final long DURATION = new ValueAnimator().getDuration();
     private static final long PAGER_DURATION = DURATION / 2;
-    private static final float BOUNCE_SCALE = 0.8f;
     private static final long CLOSE_DELAY = 600;
+    private static final long AUTO_ACTIVATE_DELAY = 100;
 
     private final Context mContext;
-    private final Paint mPathPaint;
-    private final ImageView mSettingsButton;
     private final TextView mModeText;
     private final Switch mModeSwitch;
     private final View mDivider;
     private final UntilPager mUntilPager;
     private final ProgressDots mProgressDots;
+    private final View mDivider2;
+    private final TextView mSettingsButton;
 
     private Adapter mAdapter;
     private boolean mInit;
+    private boolean mAutoActivate;
 
     public ZenModeView(Context context) {
         this(context, null);
@@ -90,29 +86,9 @@
         final int iconSize = mContext.getResources()
                 .getDimensionPixelSize(com.android.internal.R.dimen.notification_large_icon_width);
         final int topRowSize = iconSize * 2 / 3;
-        final int p = topRowSize / 7;
+        final int p = topRowSize / 3;
 
-        mPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        mPathPaint.setStyle(Paint.Style.STROKE);
-        mPathPaint.setColor(GRAY);
-        mPathPaint.setStrokeWidth(p / 2);
-
-        mSettingsButton = new ImageView(mContext);
-        mSettingsButton.setPadding(p, p, p, p);
-        mSettingsButton.setImageResource(R.drawable.ic_notify_settings_normal);
-        LayoutParams lp = new LayoutParams(topRowSize, topRowSize);
-        lp.topMargin = p;
-        lp.leftMargin = p;
-        addView(mSettingsButton, lp);
-        mSettingsButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                if (mAdapter != null) {
-                    mAdapter.configure();
-                }
-                bounce(mSettingsButton, null);
-            }
-        });
+        LayoutParams lp = null;
 
         mModeText = new TextView(mContext);
         mModeText.setText(MODE_LABEL);
@@ -120,11 +96,10 @@
         mModeText.setTextColor(GRAY);
         mModeText.setTypeface(CONDENSED);
         mModeText.setAllCaps(true);
-        mModeText.setGravity(Gravity.CENTER);
-        mModeText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mModeText.getTextSize() * 1.1f);
+        mModeText.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+        mModeText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mModeText.getTextSize() * 1.5f);
         lp = new LayoutParams(LayoutParams.WRAP_CONTENT, topRowSize);
-        lp.topMargin = p;
-        lp.addRule(CENTER_HORIZONTAL);
+        lp.leftMargin = p;
         addView(mModeText, lp);
 
         mModeSwitch = new Switch(mContext);
@@ -132,6 +107,7 @@
         mModeSwitch.setSwitchTypeface(CONDENSED);
         lp = new LayoutParams(LayoutParams.WRAP_CONTENT, topRowSize);
         lp.topMargin = p;
+        lp.rightMargin = p;
         lp.addRule(ALIGN_PARENT_RIGHT);
         lp.addRule(ALIGN_BASELINE, mModeText.getId());
         addView(mModeSwitch, lp);
@@ -154,11 +130,10 @@
         mDivider.setBackgroundColor(GRAY);
         lp = new LayoutParams(LayoutParams.MATCH_PARENT, 2);
         lp.addRule(BELOW, mModeText.getId());
-        lp.topMargin = p;
-        lp.bottomMargin = p * 2;
+        lp.bottomMargin = p;
         addView(mDivider, lp);
 
-        mUntilPager = new UntilPager(mContext, mPathPaint, iconSize * 3 / 4);
+        mUntilPager = new UntilPager(mContext, iconSize * 3 / 4);
         mUntilPager.setId(android.R.id.tabhost);
         lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         lp.leftMargin = lp.rightMargin = iconSize / 2;
@@ -167,10 +142,41 @@
         addView(mUntilPager, lp);
 
         mProgressDots = new ProgressDots(mContext, iconSize / 5);
+        mProgressDots.setId(android.R.id.progress);
         lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         lp.addRule(CENTER_HORIZONTAL);
         lp.addRule(BELOW, mUntilPager.getId());
         addView(mProgressDots, lp);
+
+        mDivider2 = new View(mContext);
+        mDivider2.setId(android.R.id.widget_frame);
+        mDivider2.setBackgroundColor(GRAY);
+        lp = new LayoutParams(LayoutParams.MATCH_PARENT, 2);
+        lp.addRule(BELOW, mProgressDots.getId());
+        addView(mDivider2, lp);
+
+        mSettingsButton = new TextView(mContext);
+        mSettingsButton.setTypeface(CONDENSED);
+        mSettingsButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSettingsButton.getTextSize() * 1.3f);
+        mSettingsButton.setPadding(p, p, p, p);
+        mSettingsButton.setText("More settings...");
+        lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+        lp.addRule(BELOW, mDivider2.getId());
+        addView(mSettingsButton, lp);
+        mSettingsButton.setOnTouchListener(new OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                if (event.getAction() == MotionEvent.ACTION_DOWN) {
+                    mSettingsButton.setBackgroundColor(DARK_GRAY);
+                } else if (event.getAction() == MotionEvent.ACTION_UP) {
+                    mSettingsButton.setBackground(null);
+                    if (mAdapter != null) {
+                        mAdapter.configure();
+                    }
+                }
+                return true;
+            }
+        });
     }
 
     public void setAdapter(Adapter adapter) {
@@ -189,6 +195,27 @@
         updateState(false);
     }
 
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mAutoActivate) {
+            mAutoActivate = false;
+            postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    if (!mModeSwitch.isChecked()) {
+                        mInit = false;
+                        mModeSwitch.setChecked(true);
+                    }
+                }
+            }, AUTO_ACTIVATE_DELAY);
+        }
+    }
+
+    public void setAutoActivate(boolean value) {
+        mAutoActivate = value;
+    }
+
     private void updateState(boolean animate) {
         mUntilPager.updateState();
         mModeSwitch.setChecked(mAdapter.getMode());
@@ -199,23 +226,6 @@
         Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
     }
 
-    private static void bounce(final View v, final Runnable midBounce) {
-        v.animate().scaleX(BOUNCE_SCALE).scaleY(BOUNCE_SCALE).setDuration(DURATION / 3)
-            .setListener(new AnimatorListenerAdapter() {
-                private boolean mFired;
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    if (!mFired) {
-                        mFired = true;
-                        if (midBounce != null) {
-                            midBounce.run();
-                        }
-                        v.animate().scaleX(1).scaleY(1).setListener(null).start();
-                    }
-                }
-            }).start();
-    }
-
     private final class UntilView extends FrameLayout {
         private static final boolean SUPPORT_LINKS = false;
 
@@ -223,7 +233,7 @@
         public UntilView(Context context) {
             super(context);
             mText = new TextView(mContext);
-            mText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mText.getTextSize() * 1.2f);
+            mText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mText.getTextSize() * 1.3f);
             mText.setTypeface(CONDENSED);
             mText.setTextColor(GRAY);
             mText.setGravity(Gravity.CENTER);
@@ -284,7 +294,7 @@
         private int mCurrent;
         private float mDownX;
 
-        public UntilPager(Context context, Paint pathPaint, int iconSize) {
+        public UntilPager(Context context, int iconSize) {
             super(context);
             mViews = new UntilView[3];
             for (int i = 0; i < mViews.length; i++) {
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 ff8ea405..04b7f53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -22,6 +22,7 @@
 import android.graphics.Canvas;
 import android.graphics.Outline;
 import android.graphics.Paint;
+
 import android.util.AttributeSet;
 import android.util.Log;
 
@@ -37,12 +38,14 @@
 import com.android.systemui.R;
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
+import com.android.systemui.statusbar.policy.ScrollAdapter;
 
 /**
  * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
  */
 public class NotificationStackScrollLayout extends ViewGroup
-        implements SwipeHelper.Callback, ExpandHelper.Callback, ExpandHelper.ScrollAdapter {
+        implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter {
 
     private static final String TAG = "NotificationStackScrollLayout";
     private static final boolean DEBUG = false;
@@ -53,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;
@@ -86,7 +89,9 @@
     /**
      * The current State this Layout is in
      */
-    private StackScrollState mCurrentStackScrollState;
+    private final StackScrollState mCurrentStackScrollState = new StackScrollState(this);
+    
+    private OnChildLocationsChangedListener mListener;
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -153,7 +158,6 @@
         // currently the padding is in the elements themself
         mPaddingBetweenElements = 0;
         mStackScrollAlgorithm = new StackScrollAlgorithm(context);
-        mCurrentStackScrollState = null;
     }
 
     @Override
@@ -188,6 +192,24 @@
         updateContentHeight();
     }
 
+    public void setChildLocationsChangedListener(OnChildLocationsChangedListener listener) {
+        mListener = listener;
+    }
+
+    /**
+     * Returns the location the given child is currently rendered at.
+     *
+     * @param child the child to get the location for
+     * @return one of {@link ViewState}'s <code>LOCATION_*</code> constants
+     */
+    public int getChildLocation(View child) {
+        ViewState childViewState = mCurrentStackScrollState.getViewStateForView(child);
+        if (childViewState == null) {
+            return ViewState.LOCATION_UNKNOWN;
+        }
+        return childViewState.location;
+    }
+
     private void setMaxLayoutHeight(int maxLayoutHeight) {
         mMaxLayoutHeight = maxLayoutHeight;
         updateAlgorithmHeight();
@@ -203,13 +225,13 @@
      */
     private void updateChildren() {
         if (!isCurrentlyAnimating()) {
-            if (mCurrentStackScrollState == null) {
-                mCurrentStackScrollState = new StackScrollState(this);
-            }
             mCurrentStackScrollState.setScrollY(mOwnScrollY);
             mStackScrollAlgorithm.getStackScrollState(mCurrentStackScrollState);
             mCurrentStackScrollState.apply();
             mOwnScrollY = mCurrentStackScrollState.getScrollY();
+            if (mListener != null) {
+                mListener.onChildLocationsChanged(this);
+            }
         } else {
             // TODO: handle animation
         }
@@ -258,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
@@ -267,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);
     }
@@ -277,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) {
@@ -344,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
@@ -365,7 +398,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         boolean scrollerWantsIt = false;
-        if (mAllowScrolling) {
+        if (!mSwipingInProgress) {
             scrollerWantsIt = onScrollTouch(ev);
         }
         boolean horizontalSwipeWantsIt = false;
@@ -388,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
@@ -418,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;
@@ -621,7 +644,7 @@
         if (getChildCount() > 0) {
             int contentHeight = getContentHeight();
             scrollRange = Math.max(0,
-                    contentHeight - mMaxLayoutHeight + mCollapsedSize);
+                    contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
         }
         return scrollRange;
     }
@@ -676,7 +699,7 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         boolean scrollWantsIt = false;
-        if (mAllowScrolling) {
+        if (!mSwipingInProgress) {
             scrollWantsIt = onInterceptTouchEventScroll(ev);
         }
         boolean swipeWantsIt = false;
@@ -742,10 +765,6 @@
                     mLastMotionY = y;
                     initVelocityTrackerIfNotExists();
                     mVelocityTracker.addMovement(ev);
-                    final ViewParent parent = getParent();
-                    if (parent != null) {
-                        parent.requestDisallowInterceptTouchEvent(true);
-                    }
                 }
                 break;
             }
@@ -802,6 +821,7 @@
     private void setIsBeingDragged(boolean isDragged) {
         mIsBeingDragged = isDragged;
         if (isDragged) {
+            requestDisallowInterceptTouchEvent(true);
             mSwipeHelper.removeLongPressCallback();
         }
     }
@@ -820,7 +840,23 @@
     }
 
     @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.
+     */
+    public interface OnChildLocationsChangedListener {
+        public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout);
+    }
 }
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 9db4e77..4745f3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.stack;
 
 import android.content.Context;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import com.android.systemui.R;
@@ -28,6 +29,8 @@
  */
 public class StackScrollAlgorithm {
 
+    private static final String LOG_TAG = "StackScrollAlgorithm";
+
     private static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
     private static final int MAX_ITEMS_IN_TOP_STACK = 3;
 
@@ -83,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;
@@ -99,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);
     }
 
@@ -130,6 +133,7 @@
             View child = hostView.getChildAt(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
             childViewState.yTranslation = currentYPosition;
+            childViewState.location = StackScrollState.ViewState.LOCATION_UNKNOWN;
             int childHeight = child.getHeight();
             // The y position after this element
             float nextYPosition = currentYPosition + childHeight + mPaddingBetweenElements;
@@ -143,12 +147,12 @@
                 nextYPosition = updateStateForTopStackChild(algorithmState,
                         numberOfElementsCompletelyIn,
                         i, childViewState);
-
             } else if (i == algorithmState.lastTopStackIndex) {
                 // 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) {
                     // Case 3:
@@ -156,8 +160,6 @@
                     // bottom of the screen so we are fully in the bottom stack
                     nextYPosition = updateStateForChildFullyInBottomStack(algorithmState,
                             transitioningPositionStart, childViewState, childHeight);
-
-
                 } else {
                     // Case 4:
                     // According to the regular scroll view we are currently translating out of /
@@ -167,7 +169,18 @@
                             currentYPosition, childViewState,
                             childHeight, nextYPosition);
                 }
+            } else {
+                childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
             }
+            // The first card is always rendered.
+            if (i == 0) {
+                childViewState.alpha = 1.0f;
+                childViewState.location = StackScrollState.ViewState.LOCATION_FIRST_CARD;
+            }
+            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;
         }
@@ -192,6 +205,8 @@
         if (childHeight != (int) newSize) {
             childViewState.height = (int) newSize;
         }
+        childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
+
         return nextYPosition;
     }
 
@@ -206,6 +221,7 @@
             nextYPosition = transitioningPositionStart
                     + mBottomStackIndentationFunctor.getValue(
                             algorithmState.itemsInBottomStack);
+            childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_PEEKING;
         } else {
             // we are fully inside the stack
             if (algorithmState.itemsInBottomStack > MAX_ITEMS_IN_BOTTOM_STACK + 2) {
@@ -214,6 +230,7 @@
                     > MAX_ITEMS_IN_BOTTOM_STACK + 1) {
                 childViewState.alpha = 1.0f - algorithmState.partialInBottom;
             }
+            childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_HIDDEN;
             nextYPosition = transitioningPositionStart + mBottomStackPeekSize;
         }
         // TODO: only temporarily collapse
@@ -237,14 +254,18 @@
             nextYPosition = mCollapsedSize + mPaddingBetweenElements -
                     mTopStackIndentationFunctor.getValue(
                             algorithmState.itemsInTopStack - i - 1);
-            if (paddedIndex == 0 && i != 0) {
+            nextYPosition = Math.min(nextYPosition, mLayoutHeight - mCollapsedSize
+                    - mBottomStackPeekSize);
+            if (paddedIndex == 0) {
                 childViewState.alpha = 1.0f - algorithmState.partialInTop;
+                childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
+            } else {
+                childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
             }
         } else {
-            // We are hidden behind the top card and faded out, so we can hide ourselfs
-            if (i != 0) {
-                childViewState.alpha = 0.0f;
-            }
+            // We are hidden behind the top card and faded out, so we can hide ourselves.
+            childViewState.alpha = 0.0f;
+            childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
         }
         return nextYPosition;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index f72a52f..881730a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -45,7 +45,7 @@
 
     public StackScrollState(ViewGroup hostView) {
         mHostView = hostView;
-        mStateMap = new HashMap<View, ViewState>(mHostView.getChildCount());
+        mStateMap = new HashMap<View, ViewState>();
     }
 
     public ViewGroup getHostView() {
@@ -144,10 +144,28 @@
     }
 
 
-    public class ViewState {
+    public static class ViewState {
+
+        // These are flags such that we can create masks for filtering.
+
+        public static final int LOCATION_UNKNOWN = 0x00;
+        public static final int LOCATION_FIRST_CARD = 0x01;
+        public static final int LOCATION_TOP_STACK_HIDDEN = 0x02;
+        public static final int LOCATION_TOP_STACK_PEEKING = 0x04;
+        public static final int LOCATION_MAIN_AREA = 0x08;
+        public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x10;
+        public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x20;
+
         float alpha;
         float yTranslation;
         float zTranslation;
         int height;
+
+        /**
+         * The location this view is currently rendered at.
+         *
+         * <p>See <code>LOCATION_</code> flags.</p>
+         */
+        int location;
     }
 }
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/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index a65f677..f1db904 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -145,6 +145,7 @@
     TypedValue mFixedWidthMinor;
     TypedValue mFixedHeightMajor;
     TypedValue mFixedHeightMinor;
+    TypedValue mOutsetBottom;
 
     // This is the top-level view of the window, containing the window decor.
     private DecorView mDecor;
@@ -2370,7 +2371,6 @@
                     } else {
                         h = 0;
                     }
-
                     if (h > 0) {
                         final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
                         heightMeasureSpec = MeasureSpec.makeMeasureSpec(
@@ -2379,6 +2379,15 @@
                 }
             }
 
+            if (mOutsetBottom != null) {
+                int mode = MeasureSpec.getMode(heightMeasureSpec);
+                if (mode != MeasureSpec.UNSPECIFIED) {
+                    int outset = (int) mOutsetBottom.getDimension(metrics);
+                    int height = MeasureSpec.getSize(heightMeasureSpec);
+                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(height + outset, mode);
+                }
+            }
+
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
             int width = getMeasuredWidth();
@@ -2993,6 +3002,10 @@
         if (a.getBoolean(com.android.internal.R.styleable.Window_windowContentTransitions, false)) {
             requestFeature(FEATURE_CONTENT_TRANSITIONS);
         }
+        if (a.hasValue(com.android.internal.R.styleable.Window_windowOutsetBottom)) {
+            if (mOutsetBottom == null) mOutsetBottom = new TypedValue();
+            a.getValue(com.android.internal.R.styleable.Window_windowOutsetBottom, mOutsetBottom);
+        }
 
         final Context context = getContext();
         final int targetSdk = context.getApplicationInfo().targetSdkVersion;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ededbb2..ccdacea 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3417,8 +3417,9 @@
             }
 
             final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
+            final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
             if (appWindow) {
-                if (showWhenLocked) {
+                if (showWhenLocked || (dismissKeyguard && !isKeyguardSecure())) {
                     mAppsToBeHidden.remove(win.getAppToken());
                 } else {
                     mAppsToBeHidden.add(win.getAppToken());
@@ -3435,8 +3436,7 @@
                             mHideLockScreen = true;
                             mForceStatusBarFromKeyguard = false;
                         }
-                        if ((fl & FLAG_DISMISS_KEYGUARD) != 0
-                                && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
+                        if (dismissKeyguard && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
                             if (DEBUG_LAYOUT) Slog.v(TAG,
                                     "Setting mDismissKeyguard true by win " + win);
                             mDismissKeyguard = mWinDismissingKeyguard == win ?
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 1a1512f..57c2f92 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2035,6 +2035,7 @@
         BackupState mCurrentState;
 
         // carried information about the current in-flight operation
+        IBackupAgent mAgentBinder;
         PackageInfo mCurrentPackage;
         File mSavedStateName;
         File mBackupDataName;
@@ -2097,6 +2098,7 @@
                 addBackupTrace(b.toString());
             }
 
+            mAgentBinder = null;
             mStatus = BackupConstants.TRANSPORT_OK;
 
             // Sanity check: if the queue is empty we have no work to do.
@@ -2228,6 +2230,7 @@
                             IApplicationThread.BACKUP_MODE_INCREMENTAL);
                     addBackupTrace("agent bound; a? = " + (agent != null));
                     if (agent != null) {
+                        mAgentBinder = agent;
                         mStatus = invokeAgentForBackup(request.packageName, agent, mTransport);
                         // at this point we'll either get a completion callback from the
                         // agent, or a timeout message on the main handler.  either way, we're
@@ -2253,6 +2256,7 @@
                 // That means we need to direct to the next state ourselves.
                 if (mStatus != BackupConstants.TRANSPORT_OK) {
                     BackupState nextState = BackupState.RUNNING_QUEUE;
+                    mAgentBinder = null;
 
                     // An agent-level failure means we reenqueue this one agent for
                     // a later retry, but otherwise proceed normally.
@@ -2274,6 +2278,7 @@
 
                     executeNextState(nextState);
                 } else {
+                    // success case
                     addBackupTrace("expecting completion/timeout callback");
                 }
             }
@@ -2402,14 +2407,52 @@
             return BackupConstants.TRANSPORT_OK;
         }
 
+        public void failAgent(IBackupAgent agent, String message) {
+            try {
+                agent.fail(message);
+            } catch (Exception e) {
+                Slog.w(TAG, "Error conveying failure to " + mCurrentPackage.packageName);
+            }
+        }
+
         @Override
         public void operationComplete() {
-            // Okay, the agent successfully reported back to us.  The next thing we do is
-            // push the app widget state for the app, if any.
+            // Okay, the agent successfully reported back to us!
             final String pkgName = mCurrentPackage.packageName;
             final long filepos = mBackupDataName.length();
             FileDescriptor fd = mBackupData.getFileDescriptor();
             try {
+                // If it's a 3rd party app, see whether they wrote any protected keys
+                // and complain mightily if they are attempting shenanigans.
+                if (mCurrentPackage.applicationInfo != null &&
+                        (mCurrentPackage.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
+                    ParcelFileDescriptor readFd = ParcelFileDescriptor.open(mBackupDataName,
+                            ParcelFileDescriptor.MODE_READ_ONLY);
+                    BackupDataInput in = new BackupDataInput(readFd.getFileDescriptor());
+                    try {
+                        while (in.readNextHeader()) {
+                            final String key = in.getKey();
+                            if (key != null && key.charAt(0) >= 0xff00) {
+                                // Not okay: crash them and bail.
+                                failAgent(mAgentBinder, "Illegal backup key: " + key);
+                                addBackupTrace("illegal key " + key + " from " + pkgName);
+                                EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
+                                        "bad key");
+                                mBackupHandler.removeMessages(MSG_TIMEOUT);
+                                agentErrorCleanup();
+                                // agentErrorCleanup() implicitly executes next state properly
+                                return;
+                            }
+                            in.skipEntityData();
+                        }
+                    } finally {
+                        if (readFd != null) {
+                            readFd.close();
+                        }
+                    }
+                }
+
+                // Piggyback the widget state payload, if any
                 BackupDataOutput out = new BackupDataOutput(fd);
                 byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName,
                         UserHandle.USER_OWNER);
@@ -2434,8 +2477,7 @@
                 }
             }
 
-            // Spin the data off to the
-            // transport and proceed with the next stage.
+            // Spin the data off to the transport and proceed with the next stage.
             if (MORE_DEBUG) Slog.v(TAG, "operationComplete(): sending data to transport for "
                     + pkgName);
             mBackupHandler.removeMessages(MSG_TIMEOUT);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 5fb6405..e69c9a4 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -445,7 +445,7 @@
                 return;
             } else if (Intent.ACTION_USER_ADDED.equals(action)
                     || Intent.ACTION_USER_REMOVED.equals(action)) {
-                updateRelatedUserIds();
+                updateCurrentProfileIds();
                 return;
             } else {
                 Slog.w(TAG, "Unexpected intent " + intent);
@@ -689,7 +689,7 @@
         // mSettings should be created before buildInputMethodListLocked
         mSettings = new InputMethodSettings(
                 mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
-        updateRelatedUserIds();
+        updateCurrentProfileIds();
         mFileManager = new InputMethodFileManager(mMethodMap, userId);
         mSwitchingController = new InputMethodSubtypeSwitchingController(mSettings);
         mSwitchingController.resetCircularListLocked(context);
@@ -805,7 +805,7 @@
 
     private void switchUserLocked(int newUserId) {
         mSettings.setCurrentUserId(newUserId);
-        updateRelatedUserIds();
+        updateCurrentProfileIds();
         // InputMethodFileManager should be reset when the user is changed
         mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
         final String defaultImiId = mSettings.getSelectedInputMethod();
@@ -826,14 +826,14 @@
         }
     }
 
-    void updateRelatedUserIds() {
-        List<UserInfo> relatedUsers =
-                UserManager.get(mContext).getRelatedUsers(mSettings.getCurrentUserId());
-        int[] relatedUserIds = new int[relatedUsers.size()]; // relatedUsers will not be null
-        for (int i = 0; i < relatedUserIds.length; i++) {
-            relatedUserIds[i] = relatedUsers.get(i).id;
+    void updateCurrentProfileIds() {
+        List<UserInfo> profiles =
+                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
+        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
+        for (int i = 0; i < currentProfileIds.length; i++) {
+            currentProfileIds[i] = profiles.get(i).id;
         }
-        mSettings.setRelatedUserIds(relatedUserIds);
+        mSettings.setCurrentProfileIds(currentProfileIds);
     }
 
     @Override
@@ -931,7 +931,7 @@
                     + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()
                     + InputMethodUtils.getApiCallStack());
         }
-        if (uid == Process.SYSTEM_UID || mSettings.isRelatedToOrCurrentUser(userId)) {
+        if (uid == Process.SYSTEM_UID || mSettings.isCurrentProfile(userId)) {
             return true;
         }
 
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index fe814fc..0d2cee8 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -30,7 +30,11 @@
 import android.database.sqlite.SQLiteStatement;
 import android.os.Binder;
 import android.os.Environment;
+import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.storage.IMountService;
+import android.os.ServiceManager;
+import android.os.storage.StorageManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -79,6 +83,7 @@
 
     private final Context mContext;
     private LockPatternUtils mLockPatternUtils;
+    private boolean mFirstCallToVold;
 
     public LockSettingsService(Context context) {
         mContext = context;
@@ -86,6 +91,7 @@
         mOpenHelper = new DatabaseHelper(mContext);
 
         mLockPatternUtils = new LockPatternUtils(context);
+        mFirstCallToVold = true;
     }
 
     public void systemReady() {
@@ -347,6 +353,51 @@
     }
 
     @Override
+        public boolean checkVoldPassword(int userId) throws RemoteException {
+        if (!mFirstCallToVold) {
+            return false;
+        }
+        mFirstCallToVold = false;
+
+        checkPasswordReadPermission(userId);
+
+        // There's no guarantee that this will safely connect, but if it fails
+        // we will simply show the lock screen when we shouldn't, so relatively
+        // benign. There is an outside chance something nasty would happen if
+        // this service restarted before vold stales out the password in this
+        // case. The nastiness is limited to not showing the lock screen when
+        // we should, within the first minute of decrypting the phone if this
+        // service can't connect to vold, it restarts, and then the new instance
+        // does successfully connect.
+        final IMountService service = getMountService();
+        String password = service.getPassword();
+        service.clearPassword();
+        if (password == null) {
+            return false;
+        }
+
+        try {
+            if (mLockPatternUtils.isLockPatternEnabled()) {
+                if (checkPattern(password, userId)) {
+                    return true;
+                }
+            }
+        } catch (Exception e) {
+        }
+
+        try {
+            if (mLockPatternUtils.isLockPasswordEnabled()) {
+                if (checkPassword(password, userId)) {
+                    return true;
+                }
+            }
+        } catch (Exception e) {
+        }
+
+        return false;
+    }
+
+    @Override
     public void removeUser(int userId) {
         checkWritePermission(userId);
 
@@ -524,4 +575,12 @@
         Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
         Secure.LOCK_SCREEN_OWNER_INFO
     };
+
+    private IMountService getMountService() {
+        final IBinder service = ServiceManager.getService("mount");
+        if (service != null) {
+            return IMountService.Stub.asInterface(service);
+        }
+        return null;
+    }
 }
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index cd74fed..b6e761c 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -74,6 +74,7 @@
 import com.google.android.collect.Maps;
 
 import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.codec.DecoderException;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
@@ -157,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.
@@ -573,6 +575,14 @@
         }
     }
 
+    private boolean isReady() {
+        try {
+            return mConnectedSignal.await(0, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            return false;
+        }
+    }
+
     private void handleSystemReady() {
         // Snapshot current volume states since it's not safe to call into vold
         // while holding locks.
@@ -2075,12 +2085,25 @@
 
     private String toHex(String password) {
         if (password == null) {
-            return null;
+            return new String();
         }
         byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
         return new String(Hex.encodeHex(bytes));
     }
 
+    private String fromHex(String hexPassword) {
+        if (hexPassword == null) {
+            return null;
+        }
+
+        try {
+            byte[] bytes = Hex.decodeHex(hexPassword.toCharArray());
+            return new String(bytes, StandardCharsets.UTF_8);
+        } catch (DecoderException e) {
+            return null;
+        }
+    }
+
     @Override
     public int decryptStorage(String password) {
         if (TextUtils.isEmpty(password)) {
@@ -2229,6 +2252,78 @@
         }
     }
 
+    /**
+     * 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()) {
+            return new String();
+        }
+
+        final NativeDaemonEvent event;
+        try {
+            event = mConnector.execute("cryptfs", "getpw");
+            return fromHex(event.getMessage());
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void clearPassword() throws RemoteException {
+        if (!isReady()) {
+            return;
+        }
+
+        final NativeDaemonEvent event;
+        try {
+            event = mConnector.execute("cryptfs", "clearpw");
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
     @Override
     public int mkdirs(String callingPkg, String appPath) {
         final int userId = UserHandle.getUserId(Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 004d4fe..e9be1d7d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -43,6 +43,7 @@
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.os.Zygote;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.MemInfoReader;
@@ -61,8 +62,6 @@
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
-import dalvik.system.Zygote;
-
 import libcore.io.IoUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -1020,7 +1019,7 @@
     final ActivityThread mSystemThread;
 
     int mCurrentUserId = 0;
-    int[] mRelatedUserIds = 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 {
@@ -1079,7 +1078,7 @@
     static final int IMMERSIVE_MODE_LOCK_MSG = 37;
     static final int PERSIST_URI_GRANTS_MSG = 38;
     static final int REQUEST_ALL_PSS_MSG = 39;
-    static final int START_RELATED_USERS_MSG = 40;
+    static final int START_PROFILES_MSG = 40;
     static final int UPDATE_TIME = 41;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -1694,9 +1693,9 @@
                 requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
                 break;
             }
-            case START_RELATED_USERS_MSG: {
+            case START_PROFILES_MSG: {
                 synchronized (ActivityManagerService.this) {
-                    startRelatedUsersLocked();
+                    startProfilesLocked();
                 }
                 break;
             }
@@ -5209,7 +5208,7 @@
                                 userId);
                     }
                 }
-                scheduleStartRelatedUsersLocked();
+                scheduleStartProfilesLocked();
             }
         }
     }
@@ -6864,8 +6863,8 @@
                             maxNum < N ? maxNum : N);
 
             final Set<Integer> includedUsers;
-            if ((flags & ActivityManager.RECENT_INCLUDE_RELATED) != 0) {
-                includedUsers = getRelatedUsersLocked(userId);
+            if ((flags & ActivityManager.RECENT_INCLUDE_PROFILES) != 0) {
+                includedUsers = getProfileIdsLocked(userId);
             } else {
                 includedUsers = new HashSet<Integer>();
             }
@@ -6900,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;
                         }
                     }
 
@@ -6980,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;
             }
         }
     }
@@ -16318,19 +16318,19 @@
      * user switch happens or when a new related user is started in the
      * background.
      */
-    private void updateRelatedUserIdsLocked() {
-        final List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(mCurrentUserId);
-        int[] relatedUserIds = new int[relatedUsers.size()]; // relatedUsers will not be null
-        for (int i = 0; i < relatedUserIds.length; i++) {
-            relatedUserIds[i] = relatedUsers.get(i).id;
+    private void updateCurrentProfileIdsLocked() {
+        final List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
+        for (int i = 0; i < currentProfileIds.length; i++) {
+            currentProfileIds[i] = profiles.get(i).id;
         }
-        mRelatedUserIds = relatedUserIds;
+        mCurrentProfileIds = currentProfileIds;
     }
 
-    private Set getRelatedUsersLocked(int userId) {
+    private Set getProfileIdsLocked(int userId) {
         Set userIds = new HashSet<Integer>();
-        final List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(userId);
-        for (UserInfo user : relatedUsers) {
+        final List<UserInfo> profiles = getUserManagerLocked().getProfiles(userId);
+        for (UserInfo user : profiles) {
             userIds.add(Integer.valueOf(user.id));
         }
         return userIds;
@@ -16391,15 +16391,15 @@
 
                 if (foreground) {
                     mCurrentUserId = userId;
-                    updateRelatedUserIdsLocked();
-                    mWindowManager.setCurrentUser(userId, mRelatedUserIds);
+                    updateCurrentProfileIdsLocked();
+                    mWindowManager.setCurrentUser(userId, mCurrentProfileIds);
                     // Once the internal notion of the active user has switched, we lock the device
                     // with the option to show the user switcher on the keyguard.
                     mWindowManager.lockNow(null);
                 } else {
                     final Integer currentUserIdInt = Integer.valueOf(mCurrentUserId);
-                    updateRelatedUserIdsLocked();
-                    mWindowManager.updateRelatedUserIds(mRelatedUserIds);
+                    updateCurrentProfileIdsLocked();
+                    mWindowManager.setCurrentProfileIds(mCurrentProfileIds);
                     mUserLru.remove(currentUserIdInt);
                     mUserLru.add(currentUserIdInt);
                 }
@@ -16619,20 +16619,21 @@
         }
     }
 
-    void scheduleStartRelatedUsersLocked() {
-        if (!mHandler.hasMessages(START_RELATED_USERS_MSG)) {
-            mHandler.sendMessageDelayed(mHandler.obtainMessage(START_RELATED_USERS_MSG),
+    void scheduleStartProfilesLocked() {
+        if (!mHandler.hasMessages(START_PROFILES_MSG)) {
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG),
                     DateUtils.SECOND_IN_MILLIS);
         }
     }
 
-    void startRelatedUsersLocked() {
-        if (DEBUG_MU) Slog.i(TAG_MU, "startRelatedUsersLocked");
-        List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(mCurrentUserId);
-        List<UserInfo> toStart = new ArrayList<UserInfo>(relatedUsers.size());
-        for (UserInfo relatedUser : relatedUsers) {
-            if ((relatedUser.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED) {
-                toStart.add(relatedUser);
+    void startProfilesLocked() {
+        if (DEBUG_MU) Slog.i(TAG_MU, "startProfilesLocked");
+        List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+        List<UserInfo> toStart = new ArrayList<UserInfo>(profiles.size());
+        for (UserInfo user : profiles) {
+            if ((user.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED
+                    && user.id != mCurrentUserId) {
+                toStart.add(user);
             }
         }
         final int n = toStart.size();
@@ -16641,7 +16642,7 @@
             startUserInBackground(toStart.get(i).id);
         }
         if (i < n) {
-            Slog.w(TAG_MU, "More related users than MAX_RUNNING_USERS");
+            Slog.w(TAG_MU, "More profiles than MAX_RUNNING_USERS");
         }
     }
 
@@ -16660,7 +16661,7 @@
                         true, false, MY_PID, Process.SYSTEM_UID, userId);
             }
 
-            startRelatedUsersLocked();
+            startProfilesLocked();
 
             int num = mUserLru.size();
             int i = 0;
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 6ee3e07..b894724 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -341,18 +341,18 @@
     }
 
     /**
-     * Checks whether the userid is either the current user or a related user.
+     * Checks whether the userid is a profile of the current user.
      */
-    private boolean isRelatedToOrCurrentUserLocked(int userId) {
-        if (mCurrentUser == userId) return true;
-        for (int i = 0; i < mService.mRelatedUserIds.length; i++) {
-            if (mService.mRelatedUserIds[i] == userId) return true;
+    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;
         }
         return false;
     }
 
     boolean okToShowLocked(ActivityRecord r) {
-        return isRelatedToOrCurrentUserLocked(r.userId)
+        return isCurrentProfileLocked(r.userId)
                 || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
     }
 
@@ -571,7 +571,7 @@
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             TaskRecord task = mTaskHistory.get(taskNdx);
-            if (!isRelatedToOrCurrentUserLocked(task.userId)) {
+            if (!isCurrentProfileLocked(task.userId)) {
                 return null;
             }
             final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -602,7 +602,7 @@
         int index = mTaskHistory.size();
         for (int i = 0; i < index; ) {
             TaskRecord task = mTaskHistory.get(i);
-            if (isRelatedToOrCurrentUserLocked(task.userId)) {
+            if (isCurrentProfileLocked(task.userId)) {
                 if (DEBUG_TASKS) Slog.d(TAG, "switchUserLocked: stack=" + getStackId() +
                         " moving " + task + " to top");
                 mTaskHistory.remove(i);
@@ -1766,10 +1766,10 @@
         mTaskHistory.remove(task);
         // Now put task at top.
         int stackNdx = mTaskHistory.size();
-        if (!isRelatedToOrCurrentUserLocked(task.userId)) {
+        if (!isCurrentProfileLocked(task.userId)) {
             // Put non-current user tasks below current user tasks.
             while (--stackNdx >= 0) {
-                if (!isRelatedToOrCurrentUserLocked(mTaskHistory.get(stackNdx).userId)) {
+                if (!isCurrentProfileLocked(mTaskHistory.get(stackNdx).userId)) {
                     break;
                 }
             }
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/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b4f7ae6..3b6d288 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -219,8 +219,8 @@
             ));
     private static final String EXTRA_INTERCEPT = "android.intercept";
 
-    // Users related to the current user.
-    final protected SparseArray<UserInfo> mRelatedUsers = new SparseArray<UserInfo>();
+    // Profiles of the current user.
+    final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
 
     private static final int MY_UID = Process.myUid();
     private static final int MY_PID = Process.myPid();
@@ -1120,9 +1120,9 @@
             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
                 // reload per-user settings
                 mSettingsObserver.update(null);
-                updateRelatedUserCache(context);
+                updateCurrentProfilesCache(context);
             } else if (action.equals(Intent.ACTION_USER_ADDED)) {
-                updateRelatedUserCache(context);
+                updateCurrentProfilesCache(context);
             }
         }
     };
@@ -2458,12 +2458,12 @@
     /**
      * Determine whether the userId applies to the notification in question, either because
      * they match exactly, or one of them is USER_ALL (which is treated as a wildcard) or
-     * because it matches a related user.
+     * because it matches one of the users profiles.
      */
-    private boolean notificationMatchesUserIdOrRelated(NotificationRecord r, int userId) {
-        synchronized (mRelatedUsers) {
+    private boolean notificationMatchesCurrentProfiles(NotificationRecord r, int userId) {
+        synchronized (mCurrentProfiles) {
             return notificationMatchesUserId(r, userId)
-                    || mRelatedUsers.get(r.getUserId()) != null;
+                    || mCurrentProfiles.get(r.getUserId()) != null;
         }
     }
 
@@ -2561,7 +2561,7 @@
         final int N = mNotificationList.size();
         for (int i=N-1; i>=0; i--) {
             NotificationRecord r = mNotificationList.get(i);
-            if (!notificationMatchesUserIdOrRelated(r, userId)) {
+            if (!notificationMatchesCurrentProfiles(r, userId)) {
                 continue;
             }
 
@@ -2676,15 +2676,15 @@
                 exceptionPackages);
     }
 
-    private void updateRelatedUserCache(Context context) {
+    private void updateCurrentProfilesCache(Context context) {
         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         int currentUserId = ActivityManager.getCurrentUser();
         if (userManager != null) {
-            List<UserInfo> relatedUsers = userManager.getRelatedUsers(currentUserId);
-            synchronized (mRelatedUsers) {
-                mRelatedUsers.clear();
-                for (UserInfo related : relatedUsers) {
-                    mRelatedUsers.put(related.id, related);
+            List<UserInfo> profiles = userManager.getProfiles(currentUserId);
+            synchronized (mCurrentProfiles) {
+                mCurrentProfiles.clear();
+                for (UserInfo user : profiles) {
+                    mCurrentProfiles.put(user.id, user);
                 }
             }
         }
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 09a414e..ff90cae 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -700,7 +700,7 @@
                                     // Just post MCS_BOUND message to trigger processing
                                     // of next pending install.
                                     if (DEBUG_SD_INSTALL) Log.i(TAG,
-                                            "Posting MCS_BOUND for next woek");
+                                            "Posting MCS_BOUND for next work");
                                     mHandler.sendEmptyMessage(MCS_BOUND);
                                 }
                             }
@@ -7533,32 +7533,34 @@
                 mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
             }
 
-            final boolean mounted;
-            if (Environment.isExternalStorageEmulated()) {
-                mounted = true;
-            } else {
-                final String status = Environment.getExternalStorageState();
-                mounted = (Environment.MEDIA_MOUNTED.equals(status)
-                        || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
-            }
+            if (mSuccess) {
+                final boolean mounted;
+                if (Environment.isExternalStorageEmulated()) {
+                    mounted = true;
+                } else {
+                    final String status = Environment.getExternalStorageState();
+                    mounted = (Environment.MEDIA_MOUNTED.equals(status)
+                            || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
+                }
 
-            if (mounted) {
-                final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
+                if (mounted) {
+                    final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
 
-                mStats.externalCacheSize = calculateDirectorySize(mContainerService,
-                        userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
+                    mStats.externalCacheSize = calculateDirectorySize(mContainerService,
+                            userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
 
-                mStats.externalDataSize = calculateDirectorySize(mContainerService,
-                        userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
+                    mStats.externalDataSize = calculateDirectorySize(mContainerService,
+                            userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
 
-                // Always subtract cache size, since it's a subdirectory
-                mStats.externalDataSize -= mStats.externalCacheSize;
+                    // Always subtract cache size, since it's a subdirectory
+                    mStats.externalDataSize -= mStats.externalCacheSize;
 
-                mStats.externalMediaSize = calculateDirectorySize(mContainerService,
-                        userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
+                    mStats.externalMediaSize = calculateDirectorySize(mContainerService,
+                            userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
 
-                mStats.externalObbSize = calculateDirectorySize(mContainerService,
-                        userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
+                    mStats.externalObbSize = calculateDirectorySize(mContainerService,
+                            userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
+                }
             }
         }
 
@@ -9199,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) {
@@ -9212,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) {
@@ -10271,6 +10284,9 @@
             final IPackageStatsObserver observer) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.GET_PACKAGE_SIZE, null);
+        if (packageName == null) {
+            throw new IllegalArgumentException("Attempt to get size of null packageName");
+        }
 
         PackageStats stats = new PackageStats(packageName, userHandle);
 
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 7f55464..a39e958 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -92,7 +92,7 @@
     private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
     private static final String ATTR_PARTIAL = "partial";
     private static final String ATTR_USER_VERSION = "version";
-    private static final String ATTR_RELATED_GROUP_ID = "relatedGroupId";
+    private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
     private static final String TAG_USERS = "users";
     private static final String TAG_USER = "user";
     private static final String TAG_RESTRICTIONS = "restrictions";
@@ -257,26 +257,26 @@
     }
 
     @Override
-    public List<UserInfo> getRelatedUsers(int userId) {
+    public List<UserInfo> getProfiles(int userId) {
         checkManageUsersPermission("query users");
         synchronized (mPackagesLock) {
             UserInfo user = getUserInfoLocked(userId);
             ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
             for (int i = 0; i < mUsers.size(); i++) {
-                UserInfo ui = mUsers.valueAt(i);
-                if (!areRelatedUsers(user, ui)) {
+                UserInfo profile = mUsers.valueAt(i);
+                if (!isProfileOf(user, profile)) {
                     continue;
                 }
-                users.add(ui);
+                users.add(profile);
             }
             return users;
         }
     }
 
-    private boolean areRelatedUsers(UserInfo user1, UserInfo user2) {
-        return user1.relatedGroupId != UserInfo.NO_RELATED_GROUP_ID &&
-                user1.relatedGroupId == user2.relatedGroupId &&
-                user1.id != user2.id;
+    private boolean isProfileOf(UserInfo user, UserInfo profile) {
+        return user.id == profile.id ||
+                (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
+                && user.profileGroupId == profile.profileGroupId);
     }
 
     @Override
@@ -684,9 +684,9 @@
             if (userInfo.partial) {
                 serializer.attribute(null, ATTR_PARTIAL, "true");
             }
-            if (userInfo.relatedGroupId != UserInfo.NO_RELATED_GROUP_ID) {
-                serializer.attribute(null, ATTR_RELATED_GROUP_ID,
-                        Integer.toString(userInfo.relatedGroupId));
+            if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
+                serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
+                        Integer.toString(userInfo.profileGroupId));
             }
 
             serializer.startTag(null, TAG_NAME);
@@ -771,7 +771,7 @@
         long salt = 0L;
         String pinHash = null;
         int failedAttempts = 0;
-        int relatedGroupId = UserInfo.NO_RELATED_GROUP_ID;
+        int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
         long lastAttemptTime = 0L;
         boolean partial = false;
         Bundle restrictions = new Bundle();
@@ -809,8 +809,14 @@
                 pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH);
                 failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0);
                 lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L);
-                relatedGroupId = readIntAttribute(parser, ATTR_RELATED_GROUP_ID,
-                        UserInfo.NO_RELATED_GROUP_ID);
+                profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
+                        UserInfo.NO_PROFILE_GROUP_ID);
+                if (profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+                    // This attribute was added and renamed during development of L.
+                    // TODO Remove upgrade path by 1st May 2014
+                    profileGroupId = readIntAttribute(parser, "relatedGroupId",
+                            UserInfo.NO_PROFILE_GROUP_ID);
+                }
                 String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
                 if ("true".equals(valueString)) {
                     partial = true;
@@ -849,7 +855,7 @@
             userInfo.creationTime = creationTime;
             userInfo.lastLoggedInTime = lastLoggedInTime;
             userInfo.partial = partial;
-            userInfo.relatedGroupId = relatedGroupId;
+            userInfo.profileGroupId = profileGroupId;
             mUserRestrictions.append(id, restrictions);
             if (salt != 0L) {
                 RestrictionsPinState pinState = mRestrictionsPinStates.get(id);
@@ -964,25 +970,25 @@
         }
     }
 
-    private int getNextRelatedGroupIdLocked() {
-        int maxGroupId = UserInfo.NO_RELATED_GROUP_ID;
+    private int getNextProfileGroupIdLocked() {
+        int maxGroupId = UserInfo.NO_PROFILE_GROUP_ID;
         for (int i = 0; i < mUsers.size(); i++) {
             UserInfo ui = mUsers.valueAt(i);
-            if (maxGroupId < ui.relatedGroupId) {
-                maxGroupId = ui.relatedGroupId;
+            if (maxGroupId < ui.profileGroupId) {
+                maxGroupId = ui.profileGroupId;
             }
         }
         return maxGroupId + 1;
     }
 
     @Override
-    public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
+    public UserInfo createProfileForUser(String name, int flags, int userId) {
         checkManageUsersPermission("Only the system can create users");
-        if (relatedUserId != UserHandle.USER_OWNER) {
-            Slog.w(LOG_TAG, "Only user owner can have related users");
+        if (userId != UserHandle.USER_OWNER) {
+            Slog.w(LOG_TAG, "Only user owner can have profiles");
             return null;
         }
-        return createUserInternal(name, flags, relatedUserId);
+        return createUserInternal(name, flags, userId);
     }
 
     @Override
@@ -991,16 +997,16 @@
         return createUserInternal(name, flags, UserHandle.USER_NULL);
     }
 
-    private UserInfo createUserInternal(String name, int flags, int relatedUserId) {
+    private UserInfo createUserInternal(String name, int flags, int profileId) {
         final long ident = Binder.clearCallingIdentity();
         UserInfo userInfo = null;
         try {
             synchronized (mInstallLock) {
                 synchronized (mPackagesLock) {
-                    UserInfo relatedUser = null;
-                    if (relatedUserId != UserHandle.USER_NULL) {
-                        relatedUser = getUserInfoLocked(relatedUserId);
-                        if (relatedUser == null) return null;
+                    UserInfo profile = null;
+                    if (profileId != UserHandle.USER_NULL) {
+                        profile = getUserInfoLocked(profileId);
+                        if (profile == null) return null;
                     }
                     if (isUserLimitReachedLocked()) return null;
                     int userId = getNextAvailableIdLocked();
@@ -1013,12 +1019,12 @@
                     Environment.getUserSystemDirectory(userInfo.id).mkdirs();
                     mUsers.put(userId, userInfo);
                     writeUserListLocked();
-                    if (relatedUser != null) {
-                        if (relatedUser.relatedGroupId == UserInfo.NO_RELATED_GROUP_ID) {
-                            relatedUser.relatedGroupId = getNextRelatedGroupIdLocked();
+                    if (profile != null) {
+                        if (profile.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+                            profile.profileGroupId = getNextProfileGroupIdLocked();
+                            writeUserLocked(profile);
                         }
-                        userInfo.relatedGroupId = relatedUser.relatedGroupId;
-                        writeUserLocked(relatedUser);
+                        userInfo.profileGroupId = profile.profileGroupId;
                     }
                     writeUserLocked(userInfo);
                     mPm.createNewUserLILPw(userId, userPath);
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/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
new file mode 100644
index 0000000..fbfca93
--- /dev/null
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -0,0 +1,110 @@
+/*
+ * 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.wm;
+
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+class CircularDisplayMask {
+    private static final String TAG = "CircularDisplayMask";
+
+    private static final int STROKE_WIDTH = 2;
+
+    private final SurfaceControl mSurfaceControl;
+    private final Surface mSurface = new Surface();
+    private int mLastDW;
+    private int mLastDH;
+    private boolean mDrawNeeded;
+    private Paint mPaint;
+
+    public CircularDisplayMask(Display display, SurfaceSession session, int zOrder) {
+        SurfaceControl ctrl = null;
+        try {
+            ctrl = new SurfaceControl(session, "CircularDisplayMask",
+                320, 290, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+            ctrl.setLayerStack(display.getLayerStack());
+            ctrl.setLayer(zOrder);
+            ctrl.setPosition(0, 0);
+            ctrl.show();
+            mSurface.copyFrom(ctrl);
+        } catch (OutOfResourcesException e) {
+        }
+        mSurfaceControl = ctrl;
+        mDrawNeeded = true;
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setColor(Color.BLACK);
+        mPaint.setStrokeWidth(STROKE_WIDTH);
+    }
+
+    private void drawIfNeeded() {
+        if (!mDrawNeeded) {
+            return;
+        }
+        mDrawNeeded = false;
+
+        Rect dirty = new Rect(0, 0, mLastDW, mLastDH);
+        Canvas c = null;
+        try {
+            c = mSurface.lockCanvas(dirty);
+        } catch (IllegalArgumentException e) {
+        } catch (Surface.OutOfResourcesException e) {
+        }
+        if (c == null) {
+            return;
+        }
+        c.drawCircle(160, 160, 160, mPaint);
+
+        mSurface.unlockCanvasAndPost(c);
+    }
+
+    // Note: caller responsible for being inside
+    // Surface.openTransaction() / closeTransaction()
+    public void setVisibility(boolean on) {
+        if (mSurfaceControl == null) {
+            return;
+        }
+        drawIfNeeded();
+        if (on) {
+            mSurfaceControl.show();
+        } else {
+            mSurfaceControl.hide();
+        }
+    }
+
+    void positionSurface(int dw, int dh) {
+        if (mLastDW == dw && mLastDH == dh) {
+            return;
+        }
+        mLastDW = dw;
+        mLastDH = dh;
+        mSurfaceControl.setSize(dw, dh);
+        mDrawNeeded = true;
+    }
+
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index dcf5880..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;
@@ -285,6 +286,8 @@
     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
     private static final String SIZE_OVERRIDE = "ro.config.size_override";
 
+    private static final String SCREEN_CIRCULAR = "ro.display.circular";
+
     private static final int MAX_SCREENSHOT_RETRIES = 3;
 
     final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -302,14 +305,14 @@
 
     /**
      * Current user when multi-user is enabled. Don't show windows of
-     * non-current user. Also see mRelatedUserIds.
+     * non-current user. Also see mCurrentProfileIds.
      */
     int mCurrentUserId;
     /**
-     * Users related to the current user. These are also allowed to show windows
+     * Users that are profiles of the current user. These are also allowed to show windows
      * on the current user.
      */
-    int[] mRelatedUserIds = new int[0];
+    int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER};
 
     final Context mContext;
 
@@ -422,6 +425,7 @@
     final SurfaceSession mFxSession;
     Watermark mWatermark;
     StrictModeFlash mStrictModeFlash;
+    CircularDisplayMask mCircularDisplayMask;
     FocusedStackFrame mFocusedStackFrame;
 
     int mFocusedStackLayer;
@@ -819,6 +823,7 @@
         }
 
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
+        showCircularDisplayMaskIfNeeded();
     }
 
     public InputMonitor getInputMonitor() {
@@ -5225,16 +5230,16 @@
         ShutdownThread.rebootSafeMode(mContext, confirm);
     }
 
-    public void updateRelatedUserIds(final int[] relatedUserIds) {
+    public void setCurrentProfileIds(final int[] currentProfileIds) {
         synchronized (mWindowMap) {
-            mRelatedUserIds = relatedUserIds;
+            mCurrentProfileIds = currentProfileIds;
         }
     }
 
-    public void setCurrentUser(final int newUserId, final int[] relatedUserIds) {
+    public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
         synchronized (mWindowMap) {
             mCurrentUserId = newUserId;
-            mRelatedUserIds = relatedUserIds;
+            mCurrentProfileIds = currentProfileIds;
             mAppTransition.setCurrentUser(newUserId);
             mPolicy.setCurrentUserLw(newUserId);
 
@@ -5250,10 +5255,10 @@
     }
 
     /* Called by WindowState */
-    boolean isRelatedToOrCurrentUserLocked(int userId) {
+    boolean isCurrentProfileLocked(int userId) {
         if (userId == mCurrentUserId) return true;
-        for (int i = 0; i < mRelatedUserIds.length; i++) {
-            if (mRelatedUserIds[i] == userId) return true;
+        for (int i = 0; i < mCurrentProfileIds.length; i++) {
+            if (mCurrentProfileIds[i] == userId) return true;
         }
         return false;
     }
@@ -5483,6 +5488,37 @@
         }
     }
 
+    public void showCircularDisplayMaskIfNeeded() {
+        if (SystemProperties.getBoolean(SCREEN_CIRCULAR, false)) {
+            mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
+        }
+    }
+
+    public void showCircularMask() {
+        synchronized(mWindowMap) {
+
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                    ">>> OPEN TRANSACTION showDisplayMask");
+            SurfaceControl.openTransaction();
+            try {
+                // TODO(multi-display): support multiple displays
+                if (mCircularDisplayMask == null) {
+                    mCircularDisplayMask = new CircularDisplayMask(
+                            getDefaultDisplayContentLocked().getDisplay(),
+                            mFxSession,
+                            mPolicy.windowTypeToLayerLw(
+                                    WindowManager.LayoutParams.TYPE_POINTER)
+                                    * TYPE_LAYER_MULTIPLIER + 10);
+                }
+                mCircularDisplayMask.setVisibility(true);
+            } finally {
+                SurfaceControl.closeTransaction();
+                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                        "<<< CLOSE TRANSACTION showDisplayMask");
+            }
+        }
+    }
+
     // TODO: more accounting of which pid(s) turned it on, keep count,
     // only allow disables from pids which have count on, etc.
     @Override
@@ -7107,6 +7143,8 @@
 
         public static final int REMOVE_STARTING_TIMEOUT = 33;
 
+        public static final int SHOW_DISPLAY_MASK = 34;
+
         @Override
         public void handleMessage(Message msg) {
             if (DEBUG_WINDOW_TRACE) {
@@ -7502,6 +7540,11 @@
                     break;
                 }
 
+                case SHOW_DISPLAY_MASK: {
+                    showCircularMask();
+                    break;
+                }
+
                 case DO_ANIMATION_CALLBACK: {
                     try {
                         ((IRemoteCallback)msg.obj).sendResult(null);
@@ -8975,6 +9018,9 @@
             if (mStrictModeFlash != null) {
                 mStrictModeFlash.positionSurface(defaultDw, defaultDh);
             }
+            if (mCircularDisplayMask != null) {
+                mCircularDisplayMask.positionSurface(defaultDw, defaultDh);
+            }
 
             boolean focusDisplayed = false;
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2c0e99e..dff75ef 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1249,7 +1249,7 @@
         }
 
         return win.mShowToOwnerOnly
-                && !mService.isRelatedToOrCurrentUserLocked(UserHandle.getUserId(win.mOwnerUid));
+                && !mService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid));
     }
 
     private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
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 ab4c89e..8f2adc8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -50,6 +50,7 @@
 
 import com.android.internal.R;
 import com.android.internal.os.BinderInternal;
+import com.android.internal.os.Zygote;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accounts.AccountManagerService;
@@ -83,7 +84,6 @@
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
 
 import java.io.File;
 import java.util.Timer;
@@ -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/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 7ae5460..9ccb809 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -17,6 +17,7 @@
 package com.android.server.usb;
 
 import android.content.Context;
+import android.content.Intent;
 import android.hardware.usb.UsbConfiguration;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
@@ -25,21 +26,25 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Scanner;
 
 /**
  * UsbHostManager manages USB state in host mode.
  */
 public class UsbHostManager {
     private static final String TAG = UsbHostManager.class.getSimpleName();
-    private static final boolean LOG = false;
+    private static final boolean DEBUG_AUDIO = false;
 
     // contains all connected USB devices
     private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>();
@@ -102,6 +107,30 @@
         return false;
     }
 
+    // Broadcasts the arrival/departure of a USB audio interface
+    // card - the ALSA card number of the physical interface
+    // device - the ALSA device number of the physical interface
+    // enabled - if true, we're connecting a device (it's arrived), else disconnecting
+    private void sendDeviceNotification(int card, int device, boolean enabled,
+        boolean hasPlayback, boolean hasCapture, boolean hasMIDI) {
+      // send a sticky broadcast containing current USB state
+      Intent intent = new Intent(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
+      intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+      intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+      intent.putExtra("state", enabled ? 1 : 0);
+      intent.putExtra("card", card);
+      intent.putExtra("device", device);
+      intent.putExtra("hasPlayback", hasPlayback);
+      intent.putExtra("hasCapture", hasCapture);
+      intent.putExtra("hasMIDI", hasMIDI);
+      mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    static boolean isBuiltInUsbDevice(String deviceName) {
+      // This may be too broad an assumption
+      return deviceName.equals("/dev/bus/usb/001/001");
+    }
+
     /* Called from JNI in monitorUsbHostBus() to report new USB devices
        Returns true if successful, in which case the JNI code will continue adding configurations,
        interfaces and endpoints, and finally call endUsbDeviceAdded after all descriptors
@@ -111,6 +140,59 @@
             int deviceClass, int deviceSubclass, int deviceProtocol,
             String manufacturerName, String productName, String serialNumber) {
 
+      if (DEBUG_AUDIO) {
+          Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")");
+          // Audio Class Codes:
+          // Audio: 0x01
+          // Audio Subclass Codes:
+          // undefined: 0x00
+          // audio control: 0x01
+          // audio streaming: 0x02
+          // midi streaming: 0x03
+
+          // some useful debugging info
+          Slog.d(TAG, "usb:UsbHostManager.usbDeviceAdded()");
+          Slog.d(TAG, "usb: nm:" + deviceName +
+              " vnd:" + vendorID +
+              " prd:" + productID +
+              " cls:" + deviceClass +
+              " sub:" + deviceSubclass +
+              " proto:" + deviceProtocol);
+      }
+
+      if (!isBuiltInUsbDevice(deviceName)) {
+          //TODO(pmclean) we will need this when we need to support USB interfaces
+          // beyond card1, device0 but turn them off for now
+          //com.android.alsascan.AlsaCardsParser cardsParser =
+          //    new com.android.alsascan.AlsaCardsParser();
+          //cardsParser.scan();
+          //cardsParser.Log();
+
+          // But we need to parse the device to determine its capabilities.
+          com.android.alsascan.AlsaDevicesParser devicesParser =
+              new com.android.alsascan.AlsaDevicesParser();
+          devicesParser.scan();
+          //devicesParser.Log();
+
+          boolean hasPlaybackDevices = devicesParser.hasPlaybackDevices();
+          boolean hasCaptureDevices = devicesParser.hasCaptureDevices();
+          boolean hasMIDI = devicesParser.hasMIDIDevices();
+
+          if (DEBUG_AUDIO) {
+              Slog.d(TAG, "usb: hasPlayback:" + hasPlaybackDevices
+                      + " hasCapture:" + hasCaptureDevices);
+          }
+
+          //TODO(pmclean)
+          // For now just assume that any USB device that is attached is:
+          // 1. An audio interface and
+          // 2. is card:1 device:0
+          int cardNum = 1;
+          int deviceNum = 0;
+          sendDeviceNotification(cardNum, deviceNum, true,
+                                 hasPlaybackDevices, hasCaptureDevices, hasMIDI);
+        }
+
         if (isBlackListed(deviceName) ||
                 isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) {
             return false;
@@ -176,6 +258,9 @@
 
     /* Called from JNI in monitorUsbHostBus() to finish adding a new device */
     private void endUsbDeviceAdded() {
+        if (DEBUG_AUDIO) {
+            Slog.d(TAG, "usb:UsbHostManager.endUsbDeviceAdded()");
+        }
         if (mNewInterface != null) {
             mNewInterface.setEndpoints(
                     mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()]));
@@ -204,6 +289,13 @@
 
     /* Called from JNI in monitorUsbHostBus to report USB device removal */
     private void usbDeviceRemoved(String deviceName) {
+        if (DEBUG_AUDIO) {
+          Slog.d(TAG, "usb:UsbHostManager.usbDeviceRemoved() nm:" + deviceName);
+        }
+
+        // Same assumptions as the fake-out above
+        sendDeviceNotification(1, 0, false, /*NA*/false, /*NA*/false, /*NA*/false);
+
         synchronized (mLock) {
             UsbDevice device = mDevices.remove(deviceName);
             if (device != null) {
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
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index cfe7525..cc621c4 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -52,9 +52,9 @@
     private final BridgeContext mContext;
     private final boolean mPlatformFile;
 
-    private ResourceValue[] mResourceData;
-    private String[] mNames;
-    private boolean[] mIsFramework;
+    private final ResourceValue[] mResourceData;
+    private final String[] mNames;
+    private final boolean[] mIsFramework;
 
     public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
             boolean platformFile) {
@@ -81,8 +81,8 @@
     }
 
     /**
-     * Seals the array after all calls to {@link #bridgeSetValue(int, String, ResourceValue)} have
-     * been done.
+     * Seals the array after all calls to
+     * {@link #bridgeSetValue(int, String, boolean, ResourceValue)} have been done.
      * <p/>This allows to compute the list of non default values, permitting
      * {@link #getIndexCount()} to return the proper value.
      */
@@ -252,7 +252,7 @@
             for (String keyword : keywords) {
                 Integer i = map.get(keyword.trim());
                 if (i != null) {
-                    result |= i.intValue();
+                    result |= i;
                 } else {
                     Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                             String.format(
@@ -731,7 +731,7 @@
         }
 
         // not a direct id valid reference? resolve it
-        Integer idValue = null;
+        Integer idValue;
 
         if (resValue.isFramework()) {
             idValue = Bridge.getResourceId(resValue.getResourceType(),
@@ -742,7 +742,7 @@
         }
 
         if (idValue != null) {
-            return idValue.intValue();
+            return idValue;
         }
 
         Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
@@ -753,6 +753,12 @@
         return defValue;
     }
 
+    @Override
+    public int getThemeAttributeId(int index, int defValue) {
+        // TODO: Get the right Theme Attribute ID to enable caching of the drawables.
+        return defValue;
+    }
+
     /**
      * Retrieve the Drawable for the attribute at <var>index</var>.  This
      * gets the resource ID of the selected attribute, and uses
@@ -854,6 +860,7 @@
      */
     @Override
     public boolean hasValue(int index) {
+        //noinspection SimplifiableIfStatement
         if (index < 0 || index >= mResourceData.length) {
             return false;
         }
diff --git a/wifi/java/android/net/wifi/BatchedScanSettings.java b/wifi/java/android/net/wifi/BatchedScanSettings.java
index f7ebc17..54801ad 100644
--- a/wifi/java/android/net/wifi/BatchedScanSettings.java
+++ b/wifi/java/android/net/wifi/BatchedScanSettings.java
@@ -34,17 +34,17 @@
     /** Used to indicate no preference for an int value */
     public final static int UNSPECIFIED = Integer.MAX_VALUE;
 
-    // TODO - make MIN/mAX dynamic and gservices adjustable.
+    // TODO - make MIN/mAX as standard for wifi batch capability requirement.
     public final static int MIN_SCANS_PER_BATCH = 2;
-    public final static int MAX_SCANS_PER_BATCH = 255;
+    public final static int MAX_SCANS_PER_BATCH = 20;
     public final static int DEFAULT_SCANS_PER_BATCH = MAX_SCANS_PER_BATCH;
 
     public final static int MIN_AP_PER_SCAN = 2;
-    public final static int MAX_AP_PER_SCAN = 255;
+    public final static int MAX_AP_PER_SCAN = 16;
     public final static int DEFAULT_AP_PER_SCAN = 16;
 
-    public final static int MIN_INTERVAL_SEC = 0;
-    public final static int MAX_INTERVAL_SEC = 3600;
+    public final static int MIN_INTERVAL_SEC = 10;
+    public final static int MAX_INTERVAL_SEC = 500;
     public final static int DEFAULT_INTERVAL_SEC = 30;
 
     public final static int MIN_AP_FOR_DISTANCE = 0;