Merge changes Iffd15e95,Id2db95ec

* changes:
  Log notification clicks
  Add userId to StatusBarNotification key
diff --git a/Android.mk b/Android.mk
index 232f5bf..8e283d7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -76,7 +76,8 @@
 	core/java/android/app/ISearchManagerCallback.aidl \
 	core/java/android/app/IServiceConnection.aidl \
 	core/java/android/app/IStopUserCallback.aidl \
-	core/java/android/app/IThumbnailReceiver.aidl \
+        core/java/android/app/task/ITaskCallback.aidl \
+        core/java/android/app/task/ITaskService.aidl \
 	core/java/android/app/IThumbnailRetriever.aidl \
 	core/java/android/app/ITransientNotification.aidl \
 	core/java/android/app/IUiAutomationConnection.aidl \
@@ -155,6 +156,7 @@
 	core/java/android/net/INetworkManagementEventObserver.aidl \
 	core/java/android/net/INetworkPolicyListener.aidl \
 	core/java/android/net/INetworkPolicyManager.aidl \
+	core/java/android/net/INetworkScoreCache.aidl \
 	core/java/android/net/INetworkScoreService.aidl \
 	core/java/android/net/INetworkStatsService.aidl \
 	core/java/android/net/INetworkStatsSession.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index c6f6a62..c841338 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -190,6 +190,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/view/IMagnificationCallbacks*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/tv/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.txt b/api/current.txt
index 54c9d90..3c4832d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -491,7 +491,7 @@
     field public static final int editTextStyle = 16842862; // 0x101006e
     field public static final deprecated int editable = 16843115; // 0x101016b
     field public static final int editorExtras = 16843300; // 0x1010224
-    field public static final int elevation = 16843852; // 0x101044c
+    field public static final int elevation = 16843853; // 0x101044d
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
@@ -501,9 +501,9 @@
     field public static final int entries = 16842930; // 0x10100b2
     field public static final int entryValues = 16843256; // 0x10101f8
     field public static final int eventsInterceptionEnabled = 16843389; // 0x101027d
-    field public static final int excludeClass = 16843854; // 0x101044e
+    field public static final int excludeClass = 16843855; // 0x101044f
     field public static final int excludeFromRecents = 16842775; // 0x1010017
-    field public static final int excludeId = 16843853; // 0x101044d
+    field public static final int excludeId = 16843854; // 0x101044e
     field public static final int exitFadeDuration = 16843533; // 0x101030d
     field public static final int expandableListPreferredChildIndicatorLeft = 16842834; // 0x1010052
     field public static final int expandableListPreferredChildIndicatorRight = 16842835; // 0x1010053
@@ -598,6 +598,7 @@
     field public static final int headerBackground = 16843055; // 0x101012f
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
     field public static final int height = 16843093; // 0x1010155
+    field public static final int hideOnContentScroll = 16843856; // 0x1010450
     field public static final int hint = 16843088; // 0x1010150
     field public static final int homeAsUpIndicator = 16843531; // 0x101030b
     field public static final int homeLayout = 16843549; // 0x101031d
@@ -1051,6 +1052,7 @@
     field public static final int sspPattern = 16843749; // 0x10103e5
     field public static final int sspPrefix = 16843748; // 0x10103e4
     field public static final int stackFromBottom = 16843005; // 0x10100fd
+    field public static final int stackViewStyle = 16843851; // 0x101044b
     field public static final int starStyle = 16842882; // 0x1010082
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startDelay = 16843746; // 0x10103e2
@@ -1108,7 +1110,7 @@
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
     field public static final int switchPreferenceStyle = 16843629; // 0x101036d
-    field public static final int switchStyle = 16843851; // 0x101044b
+    field public static final int switchStyle = 16843852; // 0x101044c
     field public static final int switchTextAppearance = 16843630; // 0x101036e
     field public static final int switchTextOff = 16843628; // 0x101036c
     field public static final int switchTextOn = 16843627; // 0x101036b
@@ -1855,52 +1857,52 @@
     field public static final int TextAppearance_Large_Inverse = 16973891; // 0x1030043
     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 = 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 = 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 = 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 = 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_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_Quantum = 16974352; // 0x1030210
+    field public static final int TextAppearance_Quantum_Body1 = 16974542; // 0x10302ce
+    field public static final int TextAppearance_Quantum_Body2 = 16974541; // 0x10302cd
+    field public static final int TextAppearance_Quantum_Button = 16974545; // 0x10302d1
+    field public static final int TextAppearance_Quantum_Caption = 16974543; // 0x10302cf
+    field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974353; // 0x1030211
+    field public static final int TextAppearance_Quantum_Display1 = 16974537; // 0x10302c9
+    field public static final int TextAppearance_Quantum_Display2 = 16974536; // 0x10302c8
+    field public static final int TextAppearance_Quantum_Display3 = 16974535; // 0x10302c7
+    field public static final int TextAppearance_Quantum_Display4 = 16974534; // 0x10302c6
+    field public static final int TextAppearance_Quantum_Headline = 16974538; // 0x10302ca
+    field public static final int TextAppearance_Quantum_Inverse = 16974354; // 0x1030212
+    field public static final int TextAppearance_Quantum_Large = 16974355; // 0x1030213
+    field public static final int TextAppearance_Quantum_Large_Inverse = 16974356; // 0x1030214
+    field public static final int TextAppearance_Quantum_Medium = 16974357; // 0x1030215
+    field public static final int TextAppearance_Quantum_Medium_Inverse = 16974358; // 0x1030216
+    field public static final int TextAppearance_Quantum_Menu = 16974544; // 0x10302d0
+    field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974359; // 0x1030217
+    field public static final int TextAppearance_Quantum_SearchResult_Title = 16974360; // 0x1030218
+    field public static final int TextAppearance_Quantum_Small = 16974361; // 0x1030219
+    field public static final int TextAppearance_Quantum_Small_Inverse = 16974362; // 0x103021a
+    field public static final int TextAppearance_Quantum_Subhead = 16974540; // 0x10302cc
+    field public static final int TextAppearance_Quantum_Title = 16974539; // 0x10302cb
+    field public static final int TextAppearance_Quantum_Widget = 16974364; // 0x103021c
+    field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974365; // 0x103021d
+    field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974366; // 0x103021e
+    field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle_Inverse = 16974367; // 0x103021f
+    field public static final int TextAppearance_Quantum_Widget_ActionBar_Title = 16974368; // 0x1030220
+    field public static final int TextAppearance_Quantum_Widget_ActionBar_Title_Inverse = 16974369; // 0x1030221
+    field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle = 16974370; // 0x1030222
+    field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle_Inverse = 16974371; // 0x1030223
+    field public static final int TextAppearance_Quantum_Widget_ActionMode_Title = 16974372; // 0x1030224
+    field public static final int TextAppearance_Quantum_Widget_ActionMode_Title_Inverse = 16974373; // 0x1030225
+    field public static final int TextAppearance_Quantum_Widget_Button = 16974374; // 0x1030226
+    field public static final int TextAppearance_Quantum_Widget_DropDownHint = 16974375; // 0x1030227
+    field public static final int TextAppearance_Quantum_Widget_DropDownItem = 16974376; // 0x1030228
+    field public static final int TextAppearance_Quantum_Widget_EditText = 16974377; // 0x1030229
+    field public static final int TextAppearance_Quantum_Widget_IconMenu_Item = 16974378; // 0x103022a
+    field public static final int TextAppearance_Quantum_Widget_PopupMenu = 16974379; // 0x103022b
+    field public static final int TextAppearance_Quantum_Widget_PopupMenu_Large = 16974380; // 0x103022c
+    field public static final int TextAppearance_Quantum_Widget_PopupMenu_Small = 16974381; // 0x103022d
+    field public static final int TextAppearance_Quantum_Widget_TabWidget = 16974382; // 0x103022e
+    field public static final int TextAppearance_Quantum_Widget_TextView = 16974383; // 0x103022f
+    field public static final int TextAppearance_Quantum_Widget_TextView_PopupMenu = 16974384; // 0x1030230
+    field public static final int TextAppearance_Quantum_Widget_TextView_SpinnerItem = 16974385; // 0x1030231
+    field public static final int TextAppearance_Quantum_WindowTitle = 16974363; // 0x103021b
     field public static final int TextAppearance_Small = 16973894; // 0x1030046
     field public static final int TextAppearance_Small_Inverse = 16973895; // 0x1030047
     field public static final int TextAppearance_StatusBar_EventContent = 16973927; // 0x1030067
@@ -1995,34 +1997,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 = 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_Quantum = 16974386; // 0x1030232
+    field public static final int Theme_Quantum_Dialog = 16974387; // 0x1030233
+    field public static final int Theme_Quantum_DialogWhenLarge = 16974391; // 0x1030237
+    field public static final int Theme_Quantum_DialogWhenLarge_NoActionBar = 16974392; // 0x1030238
+    field public static final int Theme_Quantum_Dialog_MinWidth = 16974388; // 0x1030234
+    field public static final int Theme_Quantum_Dialog_NoActionBar = 16974389; // 0x1030235
+    field public static final int Theme_Quantum_Dialog_NoActionBar_MinWidth = 16974390; // 0x1030236
+    field public static final int Theme_Quantum_InputMethod = 16974393; // 0x1030239
+    field public static final int Theme_Quantum_Light = 16974401; // 0x1030241
+    field public static final int Theme_Quantum_Light_DarkActionBar = 16974402; // 0x1030242
+    field public static final int Theme_Quantum_Light_Dialog = 16974403; // 0x1030243
+    field public static final int Theme_Quantum_Light_DialogWhenLarge = 16974407; // 0x1030247
+    field public static final int Theme_Quantum_Light_DialogWhenLarge_NoActionBar = 16974408; // 0x1030248
+    field public static final int Theme_Quantum_Light_Dialog_MinWidth = 16974404; // 0x1030244
+    field public static final int Theme_Quantum_Light_Dialog_NoActionBar = 16974405; // 0x1030245
+    field public static final int Theme_Quantum_Light_Dialog_NoActionBar_MinWidth = 16974406; // 0x1030246
+    field public static final int Theme_Quantum_Light_NoActionBar = 16974409; // 0x1030249
+    field public static final int Theme_Quantum_Light_NoActionBar_Fullscreen = 16974410; // 0x103024a
+    field public static final int Theme_Quantum_Light_NoActionBar_Overscan = 16974411; // 0x103024b
+    field public static final int Theme_Quantum_Light_NoActionBar_TranslucentDecor = 16974412; // 0x103024c
+    field public static final int Theme_Quantum_Light_Panel = 16974413; // 0x103024d
+    field public static final int Theme_Quantum_NoActionBar = 16974394; // 0x103023a
+    field public static final int Theme_Quantum_NoActionBar_Fullscreen = 16974395; // 0x103023b
+    field public static final int Theme_Quantum_NoActionBar_Overscan = 16974396; // 0x103023c
+    field public static final int Theme_Quantum_NoActionBar_TranslucentDecor = 16974397; // 0x103023d
+    field public static final int Theme_Quantum_Panel = 16974398; // 0x103023e
+    field public static final int Theme_Quantum_Wallpaper = 16974399; // 0x103023f
+    field public static final int Theme_Quantum_Wallpaper_NoTitleBar = 16974400; // 0x1030240
     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
@@ -2079,8 +2081,8 @@
     field public static final int Widget_DeviceDefault_DropDownItem_Spinner = 16974178; // 0x1030162
     field public static final int Widget_DeviceDefault_EditText = 16974154; // 0x103014a
     field public static final int Widget_DeviceDefault_ExpandableListView = 16974155; // 0x103014b
-    field public static final int Widget_DeviceDefault_FastScroll = 16974344; // 0x1030208
-    field public static final int Widget_DeviceDefault_FragmentBreadCrumbs = 16974339; // 0x1030203
+    field public static final int Widget_DeviceDefault_FastScroll = 16974346; // 0x103020a
+    field public static final int Widget_DeviceDefault_FragmentBreadCrumbs = 16974347; // 0x103020b
     field public static final int Widget_DeviceDefault_GridView = 16974156; // 0x103014c
     field public static final int Widget_DeviceDefault_HorizontalScrollView = 16974171; // 0x103015b
     field public static final int Widget_DeviceDefault_ImageButton = 16974157; // 0x103014d
@@ -2114,8 +2116,8 @@
     field public static final int Widget_DeviceDefault_Light_DropDownItem_Spinner = 16974233; // 0x1030199
     field public static final int Widget_DeviceDefault_Light_EditText = 16974206; // 0x103017e
     field public static final int Widget_DeviceDefault_Light_ExpandableListView = 16974207; // 0x103017f
-    field public static final int Widget_DeviceDefault_Light_FastScroll = 16974345; // 0x1030209
-    field public static final int Widget_DeviceDefault_Light_FragmentBreadCrumbs = 16974340; // 0x1030204
+    field public static final int Widget_DeviceDefault_Light_FastScroll = 16974349; // 0x103020d
+    field public static final int Widget_DeviceDefault_Light_FragmentBreadCrumbs = 16974350; // 0x103020e
     field public static final int Widget_DeviceDefault_Light_GridView = 16974208; // 0x1030180
     field public static final int Widget_DeviceDefault_Light_HorizontalScrollView = 16974226; // 0x1030192
     field public static final int Widget_DeviceDefault_Light_ImageButton = 16974209; // 0x1030181
@@ -2139,6 +2141,7 @@
     field public static final int Widget_DeviceDefault_Light_ScrollView = 16974225; // 0x1030191
     field public static final int Widget_DeviceDefault_Light_SeekBar = 16974220; // 0x103018c
     field public static final int Widget_DeviceDefault_Light_Spinner = 16974227; // 0x1030193
+    field public static final int Widget_DeviceDefault_Light_StackView = 16974351; // 0x103020f
     field public static final int Widget_DeviceDefault_Light_Tab = 16974237; // 0x103019d
     field public static final int Widget_DeviceDefault_Light_TabWidget = 16974229; // 0x1030195
     field public static final int Widget_DeviceDefault_Light_TextView = 16974202; // 0x103017a
@@ -2162,6 +2165,7 @@
     field public static final int Widget_DeviceDefault_ScrollView = 16974170; // 0x103015a
     field public static final int Widget_DeviceDefault_SeekBar = 16974165; // 0x1030155
     field public static final int Widget_DeviceDefault_Spinner = 16974172; // 0x103015c
+    field public static final int Widget_DeviceDefault_StackView = 16974348; // 0x103020c
     field public static final int Widget_DeviceDefault_Tab = 16974189; // 0x103016d
     field public static final int Widget_DeviceDefault_TabWidget = 16974174; // 0x103015e
     field public static final int Widget_DeviceDefault_TextView = 16974150; // 0x1030146
@@ -2172,7 +2176,7 @@
     field public static final int Widget_DropDownItem_Spinner = 16973868; // 0x103002c
     field public static final int Widget_EditText = 16973859; // 0x1030023
     field public static final int Widget_ExpandableListView = 16973860; // 0x1030024
-    field public static final int Widget_FastScroll = 16974341; // 0x1030205
+    field public static final int Widget_FastScroll = 16974337; // 0x1030201
     field public static final int Widget_FragmentBreadCrumbs = 16973961; // 0x1030089
     field public static final int Widget_Gallery = 16973877; // 0x1030035
     field public static final int Widget_GridView = 16973874; // 0x1030032
@@ -2204,8 +2208,8 @@
     field public static final int Widget_Holo_DropDownItem_Spinner = 16973995; // 0x10300ab
     field public static final int Widget_Holo_EditText = 16973971; // 0x1030093
     field public static final int Widget_Holo_ExpandableListView = 16973972; // 0x1030094
-    field public static final int Widget_Holo_FastScroll = 16974342; // 0x1030206
-    field public static final int Widget_Holo_FragmentBreadCrumbs = 16974337; // 0x1030201
+    field public static final int Widget_Holo_FastScroll = 16974339; // 0x1030203
+    field public static final int Widget_Holo_FragmentBreadCrumbs = 16974340; // 0x1030204
     field public static final int Widget_Holo_GridView = 16973973; // 0x1030095
     field public static final int Widget_Holo_HorizontalScrollView = 16973988; // 0x10300a4
     field public static final int Widget_Holo_ImageButton = 16973974; // 0x1030096
@@ -2226,7 +2230,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 = 16974542; // 0x10302ce
+    field public static final int Widget_Holo_Light_Button_Borderless = 16974342; // 0x1030206
     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
@@ -2241,7 +2245,7 @@
     field public static final int Widget_Holo_Light_EditText = 16974014; // 0x10300be
     field public static final int Widget_Holo_Light_ExpandableListView = 16974015; // 0x10300bf
     field public static final int Widget_Holo_Light_FastScroll = 16974343; // 0x1030207
-    field public static final int Widget_Holo_Light_FragmentBreadCrumbs = 16974338; // 0x1030202
+    field public static final int Widget_Holo_Light_FragmentBreadCrumbs = 16974344; // 0x1030208
     field public static final int Widget_Holo_Light_GridView = 16974016; // 0x10300c0
     field public static final int Widget_Holo_Light_HorizontalScrollView = 16974034; // 0x10300d2
     field public static final int Widget_Holo_Light_ImageButton = 16974017; // 0x10300c1
@@ -2265,6 +2269,7 @@
     field public static final int Widget_Holo_Light_ScrollView = 16974033; // 0x10300d1
     field public static final int Widget_Holo_Light_SeekBar = 16974028; // 0x10300cc
     field public static final int Widget_Holo_Light_Spinner = 16974035; // 0x10300d3
+    field public static final int Widget_Holo_Light_StackView = 16974345; // 0x1030209
     field public static final int Widget_Holo_Light_Tab = 16974052; // 0x10300e4
     field public static final int Widget_Holo_Light_TabWidget = 16974037; // 0x10300d5
     field public static final int Widget_Holo_Light_TextView = 16974010; // 0x10300ba
@@ -2288,6 +2293,7 @@
     field public static final int Widget_Holo_ScrollView = 16973987; // 0x10300a3
     field public static final int Widget_Holo_SeekBar = 16973982; // 0x103009e
     field public static final int Widget_Holo_Spinner = 16973989; // 0x10300a5
+    field public static final int Widget_Holo_StackView = 16974341; // 0x1030205
     field public static final int Widget_Holo_Tab = 16974051; // 0x10300e3
     field public static final int Widget_Holo_TabWidget = 16973991; // 0x10300a7
     field public static final int Widget_Holo_TextView = 16973967; // 0x103008f
@@ -2311,133 +2317,132 @@
     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 = 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_Quantum = 16974414; // 0x103024e
+    field public static final int Widget_Quantum_ActionBar = 16974415; // 0x103024f
+    field public static final int Widget_Quantum_ActionBar_Solid = 16974416; // 0x1030250
+    field public static final int Widget_Quantum_ActionBar_TabBar = 16974417; // 0x1030251
+    field public static final int Widget_Quantum_ActionBar_TabText = 16974418; // 0x1030252
+    field public static final int Widget_Quantum_ActionBar_TabView = 16974419; // 0x1030253
+    field public static final int Widget_Quantum_ActionButton = 16974420; // 0x1030254
+    field public static final int Widget_Quantum_ActionButton_CloseMode = 16974421; // 0x1030255
+    field public static final int Widget_Quantum_ActionButton_Overflow = 16974422; // 0x1030256
+    field public static final int Widget_Quantum_ActionMode = 16974423; // 0x1030257
+    field public static final int Widget_Quantum_AutoCompleteTextView = 16974424; // 0x1030258
+    field public static final int Widget_Quantum_Button = 16974425; // 0x1030259
+    field public static final int Widget_Quantum_ButtonBar = 16974431; // 0x103025f
+    field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974432; // 0x1030260
+    field public static final int Widget_Quantum_Button_Borderless = 16974426; // 0x103025a
+    field public static final int Widget_Quantum_Button_Borderless_Small = 16974427; // 0x103025b
+    field public static final int Widget_Quantum_Button_Inset = 16974428; // 0x103025c
+    field public static final int Widget_Quantum_Button_Small = 16974429; // 0x103025d
+    field public static final int Widget_Quantum_Button_Toggle = 16974430; // 0x103025e
+    field public static final int Widget_Quantum_CalendarView = 16974433; // 0x1030261
+    field public static final int Widget_Quantum_CheckedTextView = 16974434; // 0x1030262
+    field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974435; // 0x1030263
+    field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974436; // 0x1030264
+    field public static final int Widget_Quantum_CompoundButton_Star = 16974437; // 0x1030265
+    field public static final int Widget_Quantum_DatePicker = 16974438; // 0x1030266
+    field public static final int Widget_Quantum_DropDownItem = 16974439; // 0x1030267
+    field public static final int Widget_Quantum_DropDownItem_Spinner = 16974440; // 0x1030268
+    field public static final int Widget_Quantum_EditText = 16974441; // 0x1030269
+    field public static final int Widget_Quantum_ExpandableListView = 16974442; // 0x103026a
+    field public static final int Widget_Quantum_FastScroll = 16974443; // 0x103026b
+    field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974444; // 0x103026c
+    field public static final int Widget_Quantum_GridView = 16974445; // 0x103026d
+    field public static final int Widget_Quantum_HorizontalScrollView = 16974446; // 0x103026e
+    field public static final int Widget_Quantum_ImageButton = 16974447; // 0x103026f
+    field public static final int Widget_Quantum_Light = 16974473; // 0x1030289
+    field public static final int Widget_Quantum_Light_ActionBar = 16974474; // 0x103028a
+    field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974475; // 0x103028b
+    field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974476; // 0x103028c
+    field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974477; // 0x103028d
+    field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974478; // 0x103028e
+    field public static final int Widget_Quantum_Light_ActionButton = 16974479; // 0x103028f
+    field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974480; // 0x1030290
+    field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974481; // 0x1030291
+    field public static final int Widget_Quantum_Light_ActionMode = 16974482; // 0x1030292
+    field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974483; // 0x1030293
+    field public static final int Widget_Quantum_Light_Button = 16974484; // 0x1030294
+    field public static final int Widget_Quantum_Light_ButtonBar = 16974490; // 0x103029a
+    field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974491; // 0x103029b
+    field public static final int Widget_Quantum_Light_Button_Borderless = 16974485; // 0x1030295
+    field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974486; // 0x1030296
+    field public static final int Widget_Quantum_Light_Button_Inset = 16974487; // 0x1030297
+    field public static final int Widget_Quantum_Light_Button_Small = 16974488; // 0x1030298
+    field public static final int Widget_Quantum_Light_Button_Toggle = 16974489; // 0x1030299
+    field public static final int Widget_Quantum_Light_CalendarView = 16974492; // 0x103029c
+    field public static final int Widget_Quantum_Light_CheckedTextView = 16974493; // 0x103029d
+    field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974494; // 0x103029e
+    field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974495; // 0x103029f
+    field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974496; // 0x10302a0
+    field public static final int Widget_Quantum_Light_DropDownItem = 16974497; // 0x10302a1
+    field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974498; // 0x10302a2
+    field public static final int Widget_Quantum_Light_EditText = 16974499; // 0x10302a3
+    field public static final int Widget_Quantum_Light_ExpandableListView = 16974500; // 0x10302a4
+    field public static final int Widget_Quantum_Light_FastScroll = 16974501; // 0x10302a5
+    field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974502; // 0x10302a6
+    field public static final int Widget_Quantum_Light_GridView = 16974503; // 0x10302a7
+    field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974504; // 0x10302a8
+    field public static final int Widget_Quantum_Light_ImageButton = 16974505; // 0x10302a9
+    field public static final int Widget_Quantum_Light_ListPopupWindow = 16974506; // 0x10302aa
+    field public static final int Widget_Quantum_Light_ListView = 16974507; // 0x10302ab
+    field public static final int Widget_Quantum_Light_ListView_DropDown = 16974508; // 0x10302ac
+    field public static final int Widget_Quantum_Light_MediaRouteButton = 16974509; // 0x10302ad
+    field public static final int Widget_Quantum_Light_PopupMenu = 16974510; // 0x10302ae
+    field public static final int Widget_Quantum_Light_PopupWindow = 16974511; // 0x10302af
+    field public static final int Widget_Quantum_Light_ProgressBar = 16974512; // 0x10302b0
+    field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974513; // 0x10302b1
+    field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974514; // 0x10302b2
+    field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974515; // 0x10302b3
+    field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974516; // 0x10302b4
+    field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974517; // 0x10302b5
+    field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974518; // 0x10302b6
+    field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974519; // 0x10302b7
+    field public static final int Widget_Quantum_Light_RatingBar = 16974520; // 0x10302b8
+    field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974521; // 0x10302b9
+    field public static final int Widget_Quantum_Light_RatingBar_Small = 16974522; // 0x10302ba
+    field public static final int Widget_Quantum_Light_ScrollView = 16974523; // 0x10302bb
+    field public static final int Widget_Quantum_Light_SeekBar = 16974524; // 0x10302bc
+    field public static final int Widget_Quantum_Light_SegmentedButton = 16974525; // 0x10302bd
+    field public static final int Widget_Quantum_Light_Spinner = 16974527; // 0x10302bf
+    field public static final int Widget_Quantum_Light_StackView = 16974526; // 0x10302be
+    field public static final int Widget_Quantum_Light_Tab = 16974528; // 0x10302c0
+    field public static final int Widget_Quantum_Light_TabWidget = 16974529; // 0x10302c1
+    field public static final int Widget_Quantum_Light_TextView = 16974530; // 0x10302c2
+    field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974531; // 0x10302c3
+    field public static final int Widget_Quantum_Light_WebTextView = 16974532; // 0x10302c4
+    field public static final int Widget_Quantum_Light_WebView = 16974533; // 0x10302c5
+    field public static final int Widget_Quantum_ListPopupWindow = 16974448; // 0x1030270
+    field public static final int Widget_Quantum_ListView = 16974449; // 0x1030271
+    field public static final int Widget_Quantum_ListView_DropDown = 16974450; // 0x1030272
+    field public static final int Widget_Quantum_MediaRouteButton = 16974451; // 0x1030273
+    field public static final int Widget_Quantum_PopupMenu = 16974452; // 0x1030274
+    field public static final int Widget_Quantum_PopupWindow = 16974453; // 0x1030275
+    field public static final int Widget_Quantum_ProgressBar = 16974454; // 0x1030276
+    field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974455; // 0x1030277
+    field public static final int Widget_Quantum_ProgressBar_Large = 16974456; // 0x1030278
+    field public static final int Widget_Quantum_ProgressBar_Small = 16974457; // 0x1030279
+    field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974458; // 0x103027a
+    field public static final int Widget_Quantum_RatingBar = 16974459; // 0x103027b
+    field public static final int Widget_Quantum_RatingBar_Indicator = 16974460; // 0x103027c
+    field public static final int Widget_Quantum_RatingBar_Small = 16974461; // 0x103027d
+    field public static final int Widget_Quantum_ScrollView = 16974462; // 0x103027e
+    field public static final int Widget_Quantum_SeekBar = 16974463; // 0x103027f
+    field public static final int Widget_Quantum_SegmentedButton = 16974464; // 0x1030280
+    field public static final int Widget_Quantum_Spinner = 16974466; // 0x1030282
+    field public static final int Widget_Quantum_StackView = 16974465; // 0x1030281
+    field public static final int Widget_Quantum_Tab = 16974467; // 0x1030283
+    field public static final int Widget_Quantum_TabWidget = 16974468; // 0x1030284
+    field public static final int Widget_Quantum_TextView = 16974469; // 0x1030285
+    field public static final int Widget_Quantum_TextView_SpinnerItem = 16974470; // 0x1030286
+    field public static final int Widget_Quantum_WebTextView = 16974471; // 0x1030287
+    field public static final int Widget_Quantum_WebView = 16974472; // 0x1030288
     field public static final int Widget_RatingBar = 16973857; // 0x1030021
     field public static final int Widget_ScrollView = 16973869; // 0x103002d
     field public static final int Widget_SeekBar = 16973856; // 0x1030020
     field public static final int Widget_Spinner = 16973864; // 0x1030028
     field public static final int Widget_Spinner_DropDown = 16973955; // 0x1030083
+    field public static final int Widget_StackView = 16974338; // 0x1030202
     field public static final int Widget_TabWidget = 16973876; // 0x1030034
     field public static final int Widget_TextView = 16973858; // 0x1030022
     field public static final int Widget_TextView_PopupMenu = 16973865; // 0x1030029
@@ -3064,6 +3069,7 @@
     method public abstract android.view.View getCustomView();
     method public abstract int getDisplayOptions();
     method public abstract int getHeight();
+    method public int getHideOffset();
     method public abstract deprecated int getNavigationItemCount();
     method public abstract deprecated int getNavigationMode();
     method public abstract deprecated int getSelectedNavigationIndex();
@@ -3074,6 +3080,7 @@
     method public android.content.Context getThemedContext();
     method public abstract java.lang.CharSequence getTitle();
     method public abstract void hide();
+    method public boolean isHideOnContentScrollEnabled();
     method public abstract boolean isShowing();
     method public abstract deprecated android.app.ActionBar.Tab newTab();
     method public abstract deprecated void removeAllTabs();
@@ -3092,6 +3099,8 @@
     method public abstract void setDisplayShowHomeEnabled(boolean);
     method public abstract void setDisplayShowTitleEnabled(boolean);
     method public abstract void setDisplayUseLogoEnabled(boolean);
+    method public void setHideOffset(int);
+    method public void setHideOnContentScrollEnabled(boolean);
     method public void setHomeActionContentDescription(java.lang.CharSequence);
     method public void setHomeActionContentDescription(int);
     method public void setHomeAsUpIndicator(android.graphics.drawable.Drawable);
@@ -3307,7 +3316,6 @@
     method public final boolean requestWindowFeature(int);
     method public final void runOnUiThread(java.lang.Runnable);
     method public void setActionBar(android.widget.Toolbar);
-    method public void setActivityLabelAndIcon(java.lang.CharSequence, android.graphics.Bitmap);
     method public void setActivityTransitionListener(android.app.ActivityOptions.ActivityTransitionListener);
     method public void setContentTransitionManager(android.transition.TransitionManager);
     method public void setContentView(int);
@@ -3325,6 +3333,7 @@
     method public final void setProgressBarIndeterminate(boolean);
     method public final void setProgressBarIndeterminateVisibility(boolean);
     method public final void setProgressBarVisibility(boolean);
+    method public void setRecentsActivityValues(android.app.ActivityManager.RecentsActivityValues);
     method public void setRequestedOrientation(int);
     method public final void setResult(int);
     method public final void setResult(int, android.content.Intent);
@@ -3445,8 +3454,7 @@
     method public void readFromParcel(android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
-    field public android.graphics.Bitmap activityIcon;
-    field public java.lang.CharSequence activityLabel;
+    field public android.app.ActivityManager.RecentsActivityValues activityValues;
     field public android.content.Intent baseIntent;
     field public java.lang.CharSequence description;
     field public int id;
@@ -3454,6 +3462,21 @@
     field public int persistentId;
   }
 
+  public static class ActivityManager.RecentsActivityValues implements android.os.Parcelable {
+    ctor public ActivityManager.RecentsActivityValues(android.app.ActivityManager.RecentsActivityValues);
+    ctor public ActivityManager.RecentsActivityValues(java.lang.CharSequence, android.graphics.Bitmap, int);
+    ctor public ActivityManager.RecentsActivityValues(java.lang.CharSequence, android.graphics.Bitmap);
+    ctor public ActivityManager.RecentsActivityValues(java.lang.CharSequence);
+    ctor public ActivityManager.RecentsActivityValues();
+    method public int describeContents();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public int colorPrimary;
+    field public android.graphics.Bitmap icon;
+    field public java.lang.CharSequence label;
+  }
+
   public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable {
     ctor public ActivityManager.RunningAppProcessInfo();
     ctor public ActivityManager.RunningAppProcessInfo(java.lang.String, int, java.lang.String[]);
@@ -4985,8 +5008,10 @@
   public class DevicePolicyManager {
     method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
     method public void addUserRestriction(android.content.ComponentName, java.lang.String);
+    method public void clearForwardingIntentFilters(android.content.ComponentName);
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
     method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
+    method public void forwardMatchingIntents(android.content.ComponentName, android.content.IntentFilter, int);
     method public java.util.List<android.content.ComponentName> getActiveAdmins();
     method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
     method public boolean getCameraDisabled(android.content.ComponentName);
@@ -5046,6 +5071,8 @@
     field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
     field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "defaultManagedProfileName";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "deviceAdminPackageName";
+    field public static int FLAG_TO_MANAGED_PROFILE;
+    field public static int FLAG_TO_PRIMARY_USER;
     field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
     field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
     field public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 2; // 0x2
@@ -5162,6 +5189,27 @@
 
 }
 
+package android.app.task {
+
+  public class TaskParams implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getExtras();
+    method public int getTaskId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public abstract class TaskService extends android.app.Service {
+    ctor public TaskService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onStartTask(android.app.task.TaskParams);
+    method public abstract boolean onStopTask(android.app.task.TaskParams);
+    method public final void taskFinished(android.app.task.TaskParams, boolean);
+    field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_TASK_SERVICE";
+  }
+
+}
+
 package android.appwidget {
 
   public class AppWidgetHost {
@@ -7524,6 +7572,55 @@
     method public abstract void onStatusChanged(int);
   }
 
+  public class Task implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getBackoffPolicy();
+    method public android.os.Bundle getExtras();
+    method public long getInitialBackoffMillis();
+    method public long getIntervalMillis();
+    method public long getMaxExecutionDelayMillis();
+    method public long getMinLatencyMillis();
+    method public int getNetworkCapabilities();
+    method public java.lang.String getServiceClassName();
+    method public int getTaskId();
+    method public boolean isPeriodic();
+    method public boolean isRequireCharging();
+    method public boolean isRequireDeviceIdle();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static abstract interface Task.BackoffPolicy {
+    field public static final int EXPONENTIAL = 1; // 0x1
+    field public static final int LINEAR = 0; // 0x0
+  }
+
+  public final class Task.Builder {
+    ctor public Task.Builder(int, java.lang.Class<android.app.task.TaskService>);
+    method public android.content.Task build();
+    method public android.content.Task.Builder setBackoffCriteria(long, int);
+    method public android.content.Task.Builder setExtras(android.os.Bundle);
+    method public android.content.Task.Builder setMinimumLatency(long);
+    method public android.content.Task.Builder setOverrideDeadline(long);
+    method public android.content.Task.Builder setPeriodic(long);
+    method public android.content.Task.Builder setRequiredNetworkCapabilities(int);
+    method public android.content.Task.Builder setRequiresCharging(boolean);
+    method public android.content.Task.Builder setRequiresDeviceIdle(boolean);
+  }
+
+  public static abstract interface Task.NetworkType {
+    field public static final int ANY = 0; // 0x0
+    field public static final int UNMETERED = 1; // 0x1
+  }
+
+  public abstract class TaskManager {
+    ctor public TaskManager();
+    method public abstract void cancel(int);
+    method public abstract void cancelAll();
+    method public abstract java.util.List<android.content.Task> getAllPendingTasks();
+    method public abstract int schedule(android.content.Task);
+  }
+
   public class UriMatcher {
     ctor public UriMatcher(int);
     method public void addURI(java.lang.String, java.lang.String, int);
@@ -7762,6 +7859,8 @@
   public class LauncherApps {
     method public synchronized void addOnAppsChangedListener(android.content.pm.LauncherApps.OnAppsChangedListener);
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
+    method public boolean isActivityEnabledForProfile(android.content.ComponentName, android.os.UserHandle);
+    method public boolean isPackageEnabledForProfile(java.lang.String, android.os.UserHandle);
     method public synchronized void removeOnAppsChangedListener(android.content.pm.LauncherApps.OnAppsChangedListener);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
     method public void startActivityForProfile(android.content.ComponentName, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
@@ -12132,6 +12231,14 @@
     field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_MODE;
   }
 
+  public final class ColorSpaceTransform {
+    ctor public ColorSpaceTransform(android.hardware.camera2.Rational[]);
+    ctor public ColorSpaceTransform(int[]);
+    method public void copyElements(android.hardware.camera2.Rational[], int);
+    method public void copyElements(int[], int);
+    method public android.hardware.camera2.Rational getElement(int, int);
+  }
+
   public final class Face {
     method public android.graphics.Rect getBounds();
     method public int getId();
@@ -12144,18 +12251,83 @@
     field public static final int SCORE_MIN = 1; // 0x1
   }
 
+  public final class LensShadingMap {
+    method public void copyGainFactors(float[], int);
+    method public int getColumnCount();
+    method public float getGainFactor(int, int, int);
+    method public int getGainFactorCount();
+    method public android.hardware.camera2.RggbChannelVector getGainFactorVector(int, int);
+    method public int getRowCount();
+    field public static final float MINIMUM_GAIN_FACTOR = 1.0f;
+  }
+
+  public final class MeteringRectangle {
+    ctor public MeteringRectangle(int, int, int, int, int);
+    ctor public MeteringRectangle(android.graphics.Point, android.util.Size, int);
+    ctor public MeteringRectangle(android.graphics.Rect, int);
+    method public boolean equals(android.hardware.camera2.MeteringRectangle);
+    method public int getHeight();
+    method public int getMeteringWeight();
+    method public android.graphics.Rect getRect();
+    method public android.util.Size getSize();
+    method public android.graphics.Point getUpperLeftPoint();
+    method public int getWidth();
+    method public int getX();
+    method public int getY();
+  }
+
   public final class Rational {
     ctor public Rational(int, int);
     method public int getDenominator();
     method public int getNumerator();
   }
 
+  public final class RggbChannelVector {
+    ctor public RggbChannelVector(float, float, float, float);
+    method public void copyTo(float[], int);
+    method public float getBlue();
+    method public float getComponent(int);
+    method public float getGreenEven();
+    method public float getGreenOdd();
+    method public final float getRed();
+    field public static final int BLUE = 3; // 0x3
+    field public static final int COUNT = 4; // 0x4
+    field public static final int GREEN_EVEN = 1; // 0x1
+    field public static final int GREEN_ODD = 2; // 0x2
+    field public static final int RED = 0; // 0x0
+  }
+
   public final class Size {
     ctor public Size(int, int);
     method public final int getHeight();
     method public final int getWidth();
   }
 
+  public final class StreamConfigurationMap {
+    method public final int[] getOutputFormats();
+    method public long getOutputMinFrameDuration(int, android.util.Size);
+    method public long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
+    method public android.util.Size[] getOutputSizes(java.lang.Class<T>);
+    method public android.util.Size[] getOutputSizes(int);
+    method public long getOutputStallDuration(int, android.util.Size);
+    method public long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
+    method public boolean isOutputSupportedFor(int);
+    method public static boolean isOutputSupportedFor(java.lang.Class<T>);
+    method public boolean isOutputSupportedFor(android.view.Surface);
+  }
+
+  public final class TonemapCurve {
+    method public void copyColorCurve(int, float[], int);
+    method public android.graphics.PointF getPoint(int, int);
+    method public int getPointCount(int);
+    field public static final int CHANNEL_BLUE = 2; // 0x2
+    field public static final int CHANNEL_GREEN = 1; // 0x1
+    field public static final int CHANNEL_RED = 0; // 0x0
+    field public static final float LEVEL_BLACK = 0.0f;
+    field public static final float LEVEL_WHITE = 1.0f;
+    field public static final int POINT_SIZE = 2; // 0x2
+  }
+
 }
 
 package android.hardware.display {
@@ -12198,7 +12370,6 @@
     method public static boolean isValidType(int);
     field public static final int ADDR_AUDIO_SYSTEM = 5; // 0x5
     field public static final int ADDR_BROADCAST = 15; // 0xf
-    field public static final int ADDR_FREE_USE = 14; // 0xe
     field public static final int ADDR_INVALID = -1; // 0xffffffff
     field public static final int ADDR_PLAYBACK_1 = 4; // 0x4
     field public static final int ADDR_PLAYBACK_2 = 8; // 0x8
@@ -12208,6 +12379,7 @@
     field public static final int ADDR_RECORDER_3 = 9; // 0x9
     field public static final int ADDR_RESERVED_1 = 12; // 0xc
     field public static final int ADDR_RESERVED_2 = 13; // 0xd
+    field public static final int ADDR_SPECIFIC_USE = 14; // 0xe
     field public static final int ADDR_TUNER_1 = 3; // 0x3
     field public static final int ADDR_TUNER_2 = 6; // 0x6
     field public static final int ADDR_TUNER_3 = 7; // 0x7
@@ -12288,6 +12460,7 @@
     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
+    field public static final int UNKNOWN_VENDOR_ID = 16777215; // 0xffffff
   }
 
   public final class HdmiCecClient {
@@ -12305,6 +12478,17 @@
     method public void onMessageReceived(android.hardware.hdmi.HdmiCecMessage);
   }
 
+  public final class HdmiCecDeviceInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getDeviceType();
+    method public java.lang.String getDisplayName();
+    method public int getLogicalAddress();
+    method public int getPhysicalAddress();
+    method public int getVendorId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public final class HdmiCecManager {
     method public android.hardware.hdmi.HdmiCecClient getClient(int, android.hardware.hdmi.HdmiCecClient.Listener);
   }
@@ -12318,6 +12502,7 @@
     method public int getSource();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final byte[] EMPTY_PARAM;
   }
 
 }
@@ -15097,11 +15282,13 @@
 package android.media.session {
 
   public final class MediaMetadata implements android.os.Parcelable {
+    method public boolean containsKey(java.lang.String);
     method public int describeContents();
     method public android.graphics.Bitmap getBitmap(java.lang.String);
     method public long getLong(java.lang.String);
     method public android.media.Rating getRating(java.lang.String);
     method public java.lang.String getString(java.lang.String);
+    method public int size();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final java.lang.String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
@@ -15112,6 +15299,7 @@
     field public static final java.lang.String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
     field public static final java.lang.String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
     field public static final java.lang.String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
+    field public static final java.lang.String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
     field public static final java.lang.String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
     field public static final java.lang.String METADATA_KEY_DATE = "android.media.metadata.DATE";
     field public static final java.lang.String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
@@ -15144,25 +15332,25 @@
     method public long getBufferPosition();
     method public java.lang.String getErrorMessage();
     method public long getPosition();
-    method public float getSpeed();
+    method public float getRate();
     method public int getState();
     method public void setActions(long);
     method public void setBufferPosition(long);
     method public void setErrorMessage(java.lang.String);
-    method public void setPosition(long);
-    method public void setSpeed(float);
-    method public void setState(int);
+    method public void setState(int, long, float);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final long ACTION_FASTFORWARD = 64L; // 0x40L
     field public static final long ACTION_NEXT_ITEM = 32L; // 0x20L
     field public static final long ACTION_PAUSE = 2L; // 0x2L
     field public static final long ACTION_PLAY = 4L; // 0x4L
+    field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L
     field public static final long ACTION_PREVIOUS_ITEM = 16L; // 0x10L
     field public static final long ACTION_RATING = 128L; // 0x80L
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
     field public static final int PLAYSTATE_BUFFERING = 6; // 0x6
     field public static final int PLAYSTATE_CONNECTING = 8; // 0x8
     field public static final int PLAYSTATE_ERROR = 7; // 0x7
@@ -15171,6 +15359,8 @@
     field public static final int PLAYSTATE_PAUSED = 2; // 0x2
     field public static final int PLAYSTATE_PLAYING = 3; // 0x3
     field public static final int PLAYSTATE_REWINDING = 5; // 0x5
+    field public static final int PLAYSTATE_SKIPPING_BACKWARDS = 9; // 0x9
+    field public static final int PLAYSTATE_SKIPPING_FORWARDS = 10; // 0xa
     field public static final int PLAYSTATE_STOPPED = 1; // 0x1
   }
 
@@ -24940,23 +25130,53 @@
   public class VoiceInteractionService extends android.app.Service {
     ctor public VoiceInteractionService();
     method public android.os.IBinder onBind(android.content.Intent);
-    method public void startVoiceActivity(android.content.Intent, android.os.Bundle);
+    method public void startSession(android.os.Bundle);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
     field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
   }
 
-  public abstract class VoiceInteractionSession {
+  public abstract class VoiceInteractionSession implements android.view.KeyEvent.Callback {
     ctor public VoiceInteractionSession(android.content.Context);
     ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
+    method public void finish();
+    method public android.view.LayoutInflater getLayoutInflater();
+    method public android.app.Dialog getWindow();
+    method public void hideWindow();
+    method public void onBackPressed();
     method public abstract void onCancel(android.service.voice.VoiceInteractionSession.Request);
+    method public void onCloseSystemDialogs();
     method public abstract void onCommand(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
+    method public void onComputeInsets(android.service.voice.VoiceInteractionSession.Insets);
     method public abstract void onConfirm(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
+    method public void onCreate(android.os.Bundle);
+    method public android.view.View onCreateContentView();
+    method public void onDestroy();
     method public abstract boolean[] onGetSupportedCommands(android.service.voice.VoiceInteractionSession.Caller, java.lang.String[]);
+    method public boolean onKeyDown(int, android.view.KeyEvent);
+    method public boolean onKeyLongPress(int, android.view.KeyEvent);
+    method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+    method public boolean onKeyUp(int, android.view.KeyEvent);
+    method public void onTaskFinished(android.content.Intent, int);
+    method public void onTaskStarted(android.content.Intent, int);
+    method public void setContentView(android.view.View);
+    method public void setTheme(int);
+    method public void showWindow();
+    method public void startVoiceActivity(android.content.Intent);
   }
 
   public static class VoiceInteractionSession.Caller {
   }
 
+  public static final class VoiceInteractionSession.Insets {
+    ctor public VoiceInteractionSession.Insets();
+    field public static final int TOUCHABLE_INSETS_CONTENT = 1; // 0x1
+    field public static final int TOUCHABLE_INSETS_FRAME = 0; // 0x0
+    field public static final int TOUCHABLE_INSETS_REGION = 3; // 0x3
+    field public int contentTopInsets;
+    field public int touchableInsets;
+    field public final android.graphics.Region touchableRegion;
+  }
+
   public static class VoiceInteractionSession.Request {
     method public void sendCancelResult();
     method public void sendCommandResult(boolean, android.os.Bundle);
@@ -28608,6 +28828,25 @@
     method public void set(T, V);
   }
 
+  public final class Range {
+    ctor public Range(T, T);
+    method public static android.util.Range<T> create(T, T);
+    method public T getLower();
+    method public T getUpper();
+  }
+
+  public final class Size {
+    ctor public Size(int, int);
+    method public int getHeight();
+    method public int getWidth();
+  }
+
+  public final class SizeF {
+    ctor public SizeF(float, float);
+    method public float getHeight();
+    method public float getWidth();
+  }
+
   public class SparseArray implements java.lang.Cloneable {
     ctor public SparseArray();
     ctor public SparseArray(int);
@@ -30105,7 +30344,7 @@
     method public boolean dispatchKeyEvent(android.view.KeyEvent);
     method public boolean dispatchKeyEventPreIme(android.view.KeyEvent);
     method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
-    method public boolean dispatchNestedFling(float, float);
+    method public boolean dispatchNestedFling(float, float, boolean);
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
@@ -30740,10 +30979,11 @@
   public class ViewConfiguration {
     ctor public deprecated ViewConfiguration();
     method public static android.view.ViewConfiguration get(android.content.Context);
+    method public long getDeviceGlobalActionKeyTimeout();
     method public static int getDoubleTapTimeout();
     method public static deprecated int getEdgeSlop();
     method public static deprecated int getFadingEdgeLength();
-    method public static long getGlobalActionKeyTimeout();
+    method public static deprecated long getGlobalActionKeyTimeout();
     method public static int getJumpTapTimeout();
     method public static int getKeyRepeatDelay();
     method public static int getKeyRepeatTimeout();
@@ -30898,7 +31138,7 @@
     method public boolean onInterceptHoverEvent(android.view.MotionEvent);
     method public boolean onInterceptTouchEvent(android.view.MotionEvent);
     method protected abstract void onLayout(boolean, int, int, int, int);
-    method public boolean onNestedFling(android.view.View, float, float);
+    method public boolean onNestedFling(android.view.View, float, float, boolean);
     method public void onNestedPreScroll(android.view.View, int, int, int[]);
     method public void onNestedScroll(android.view.View, int, int, int, int);
     method public void onNestedScrollAccepted(android.view.View, android.view.View, int);
@@ -31036,7 +31276,7 @@
     method public abstract boolean isTextAlignmentResolved();
     method public abstract boolean isTextDirectionResolved();
     method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
-    method public abstract boolean onNestedFling(android.view.View, float, float);
+    method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
     method public abstract void onNestedPreScroll(android.view.View, int, int, int[]);
     method public abstract void onNestedScroll(android.view.View, int, int, int, int);
     method public abstract void onNestedScrollAccepted(android.view.View, android.view.View, int);
@@ -32591,6 +32831,16 @@
 
 package android.webkit {
 
+  public abstract interface ClientCertRequest {
+    method public abstract void cancel();
+    method public abstract java.lang.String getHost();
+    method public abstract java.lang.String[] getKeyTypes();
+    method public abstract int getPort();
+    method public abstract java.security.Principal[] getPrincipals();
+    method public abstract void ignore();
+    method public abstract void proceed(java.security.PrivateKey, java.security.cert.X509Certificate[]);
+  }
+
   public class ConsoleMessage {
     ctor public ConsoleMessage(java.lang.String, java.lang.String, int, android.webkit.ConsoleMessage.MessageLevel);
     method public int lineNumber();
@@ -32819,6 +33069,7 @@
     method public boolean getMediaPlaybackRequiresUserGesture();
     method public synchronized int getMinimumFontSize();
     method public synchronized int getMinimumLogicalFontSize();
+    method public abstract int getMixedContentMode();
     method public deprecated synchronized android.webkit.WebSettings.PluginState getPluginState();
     method public synchronized java.lang.String getSansSerifFontFamily();
     method public boolean getSaveFormData();
@@ -32863,6 +33114,7 @@
     method public void setMediaPlaybackRequiresUserGesture(boolean);
     method public synchronized void setMinimumFontSize(int);
     method public synchronized void setMinimumLogicalFontSize(int);
+    method public abstract void setMixedContentMode(int);
     method public void setNeedInitialFocus(boolean);
     method public deprecated synchronized void setPluginState(android.webkit.WebSettings.PluginState);
     method public deprecated synchronized void setRenderPriority(android.webkit.WebSettings.RenderPriority);
@@ -32884,6 +33136,9 @@
     field public static final int LOAD_DEFAULT = -1; // 0xffffffff
     field public static final deprecated int LOAD_NORMAL = 0; // 0x0
     field public static final int LOAD_NO_CACHE = 2; // 0x2
+    field public static final int MIXED_CONTENT_ALWAYS_ALLOW = 0; // 0x0
+    field public static final int MIXED_CONTENT_COMPATIBILITY_MODE = 2; // 0x2
+    field public static final int MIXED_CONTENT_NEVER_ALLOW = 1; // 0x1
   }
 
   public static final class WebSettings.LayoutAlgorithm extends java.lang.Enum {
@@ -32976,6 +33231,7 @@
     method public deprecated boolean canZoomOut();
     method public deprecated android.graphics.Picture capturePicture();
     method public void clearCache(boolean);
+    method public static void clearClientCertPreferences(java.lang.Runnable);
     method public void clearFormData();
     method public void clearHistory();
     method public void clearMatches();
@@ -33092,13 +33348,15 @@
     method public void onLoadResource(android.webkit.WebView, java.lang.String);
     method public void onPageFinished(android.webkit.WebView, java.lang.String);
     method public void onPageStarted(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
+    method public void onReceivedClientCertRequest(android.webkit.WebView, android.webkit.ClientCertRequest);
     method public void onReceivedError(android.webkit.WebView, int, java.lang.String, java.lang.String);
     method public void onReceivedHttpAuthRequest(android.webkit.WebView, android.webkit.HttpAuthHandler, java.lang.String, java.lang.String);
     method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
     method public void onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError);
     method public void onScaleChanged(android.webkit.WebView, float, float);
     method public deprecated void onTooManyRedirects(android.webkit.WebView, android.os.Message, android.os.Message);
-    method public void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent);
+    method public void onUnhandledInputEvent(android.webkit.WebView, android.view.InputEvent);
+    method public deprecated void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent);
     method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebView, java.lang.String);
     method public boolean shouldOverrideKeyEvent(android.webkit.WebView, android.view.KeyEvent);
     method public boolean shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String);
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 391c197..74ccbc2 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -145,7 +145,7 @@
     static const char kInstructionSet[] = "x86_64";
 #elif defined(__arm__)
     static const char kInstructionSet[] = "arm";
-#elif defined(__x86__)
+#elif defined(__i386__)
     static const char kInstructionSet[] = "x86";
 #elif defined (__mips__)
     static const char kInstructionSet[] = "mips";
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 1780e03..3dc024ed 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -156,12 +156,12 @@
     return NO_ERROR;
 }
 
-status_t BootAnimation::initTexture(void* buffer, size_t len)
+status_t BootAnimation::initTexture(const Animation::Frame& frame)
 {
     //StopWatch watch("blah");
 
     SkBitmap bitmap;
-    SkMemoryStream  stream(buffer, len);
+    SkMemoryStream  stream(frame.map->getDataPtr(), frame.map->getDataLength());
     SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
     if (codec) {
         codec->setDitherImage(false);
@@ -171,6 +171,11 @@
         delete codec;
     }
 
+    // FileMap memory is never released until application exit.
+    // Release it now as the texture is already loaded and the memory used for
+    // the packed resource can be released.
+    frame.map->release();
+
     // ensure we can call getPixels(). No need to call unlock, since the
     // bitmap will go out of scope when we return from this method.
     bitmap.lockPixels();
@@ -409,6 +414,7 @@
 
     String8 desString((char const*)descMap->getDataPtr(),
             descMap->getDataLength());
+    descMap->release();
     char const* s = desString.string();
 
     Animation animation;
@@ -533,9 +539,7 @@
                         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                     }
-                    initTexture(
-                            frame.map->getDataPtr(),
-                            frame.map->getDataLength());
+                    initTexture(frame);
                 }
 
                 if (!clearReg.isEmpty()) {
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 22963c2..ba1c507 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -79,7 +79,7 @@
     };
 
     status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
-    status_t initTexture(void* buffer, size_t len);
+    status_t initTexture(const Animation::Frame& frame);
     bool android();
     bool movie();
 
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 04f62e3..3c3df01 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -932,6 +932,66 @@
      */
     public void setHomeActionContentDescription(int resId) { }
 
+    /**
+     * Enable hiding the action bar on content scroll.
+     *
+     * <p>If enabled, the action bar will scroll out of sight along with a
+     * {@link View#setNestedScrollingEnabled(boolean) nested scrolling child} view's content.
+     * The action bar must be in {@link Window#FEATURE_ACTION_BAR_OVERLAY overlay mode}
+     * to enable hiding on content scroll.</p>
+     *
+     * <p>When partially scrolled off screen the action bar is considered
+     * {@link #hide() hidden}. A call to {@link #show() show} will cause it to return to full view.
+     * </p>
+     * @param hideOnContentScroll true to enable hiding on content scroll.
+     */
+    public void setHideOnContentScrollEnabled(boolean hideOnContentScroll) {
+        if (hideOnContentScroll) {
+            throw new UnsupportedOperationException("Hide on content scroll is not supported in " +
+                    "this action bar configuration.");
+        }
+    }
+
+    /**
+     * Return whether the action bar is configured to scroll out of sight along with
+     * a {@link View#setNestedScrollingEnabled(boolean) nested scrolling child}.
+     *
+     * @return true if hide-on-content-scroll is enabled
+     * @see #setHideOnContentScrollEnabled(boolean)
+     */
+    public boolean isHideOnContentScrollEnabled() {
+        return false;
+    }
+
+    /**
+     * Return the current vertical offset of the action bar.
+     *
+     * <p>The action bar's current hide offset is the distance that the action bar is currently
+     * scrolled offscreen in pixels. The valid range is 0 (fully visible) to the action bar's
+     * current measured {@link #getHeight() height} (fully invisible).</p>
+     *
+     * @return The action bar's offset toward its fully hidden state in pixels
+     */
+    public int getHideOffset() {
+        return 0;
+    }
+
+    /**
+     * Set the current hide offset of the action bar.
+     *
+     * <p>The action bar's current hide offset is the distance that the action bar is currently
+     * scrolled offscreen in pixels. The valid range is 0 (fully visible) to the action bar's
+     * current measured {@link #getHeight() height} (fully invisible).</p>
+     *
+     * @param offset The action bar's offset toward its fully hidden state in pixels.
+     */
+    public void setHideOffset(int offset) {
+        if (offset != 0) {
+            throw new UnsupportedOperationException("Setting an explicit action bar hide offset " +
+                    "is not supported in this action bar configuration.");
+        }
+    }
+
     /** @hide */
     public void setDefaultDisplayHomeAsUpEnabled(boolean enabled) {
     }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8981c88..5ec3117 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3493,6 +3493,16 @@
             }
             theme.applyStyle(resid, false);
         }
+
+        // Get the primary color and update the RecentsActivityValues for this activity
+        TypedArray a = getTheme().obtainStyledAttributes(com.android.internal.R.styleable.Theme);
+        int colorPrimary = a.getColor(com.android.internal.R.styleable.Theme_colorPrimary, 0);
+        a.recycle();
+        if (colorPrimary != 0) {
+            ActivityManager.RecentsActivityValues v = new ActivityManager.RecentsActivityValues();
+            v.colorPrimary = colorPrimary;
+            setRecentsActivityValues(v);
+        }
     }
 
     /**
@@ -4779,31 +4789,26 @@
     }
 
     /**
-     * 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}.
+     * Sets information describing this Activity for presentation inside the Recents System UI. When
+     * {@link ActivityManager#getRecentTasks} is called, the activities of each task are
+     * traversed in order from the topmost activity to the bottommost. The traversal continues for
+     * each property until a suitable value is found. For each task those values will be returned in
+     * {@link android.app.ActivityManager.RecentsActivityValues}.
      *
      * @see ActivityManager#getRecentTasks
-     * @see ActivityManager.RecentTaskInfo
+     * @see android.app.ActivityManager.RecentsActivityValues
      *
-     * @param activityLabel The label to use in the RecentTaskInfo.
-     * @param activityIcon The Bitmap to use in the RecentTaskInfo.
+     * @param values The Recents values that describe this activity.
      */
-    public void setActivityLabelAndIcon(CharSequence activityLabel, Bitmap activityIcon) {
-        final Bitmap scaledIcon;
-        if (activityIcon != null) {
+    public void setRecentsActivityValues(ActivityManager.RecentsActivityValues values) {
+        ActivityManager.RecentsActivityValues activityValues =
+                new ActivityManager.RecentsActivityValues(values);
+        if (values.icon != null) {
             final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
-            scaledIcon = Bitmap.createScaledBitmap(activityIcon, size, size, true);
-        } else {
-            scaledIcon = null;
+            activityValues.icon = Bitmap.createScaledBitmap(values.icon, size, size, true);
         }
         try {
-            ActivityManagerNative.getDefault().setActivityLabelAndIcon(mToken, activityLabel,
-                    scaledIcon);
+            ActivityManagerNative.getDefault().setRecentsActivityValues(mToken, activityValues);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 018e949..5d809d8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -475,6 +475,111 @@
     }
 
     /**
+     * Information you can set and retrieve about the current activity within Recents.
+     */
+    public static class RecentsActivityValues implements Parcelable {
+        public CharSequence label;
+        public Bitmap icon;
+        public int colorPrimary;
+
+        public RecentsActivityValues(RecentsActivityValues values) {
+            copyFrom(values);
+        }
+
+        /**
+         * Creates the RecentsActivityValues to the specified values.
+         *
+         * @param label A label and description of the current state of this activity.
+         * @param icon An icon that represents the current state of this activity.
+         * @param color A color to override the theme's primary color.
+         */
+        public RecentsActivityValues(CharSequence label, Bitmap icon, int color) {
+            this.label = label;
+            this.icon = icon;
+            this.colorPrimary = color;
+        }
+
+        /**
+         * Creates the RecentsActivityValues to the specified values.
+         *
+         * @param label A label and description of the current state of this activity.
+         * @param icon An icon that represents the current state of this activity.
+         */
+        public RecentsActivityValues(CharSequence label, Bitmap icon) {
+            this(label, icon, 0);
+        }
+
+        /**
+         * Creates the RecentsActivityValues to the specified values.
+         *
+         * @param label A label and description of the current state of this activity.
+         */
+        public RecentsActivityValues(CharSequence label) {
+            this(label, null, 0);
+        }
+
+        public RecentsActivityValues() {
+            this(null, null, 0);
+        }
+
+        private RecentsActivityValues(Parcel source) {
+            readFromParcel(source);
+        }
+
+        /**
+         * Do a shallow copy of another set of activity values.
+         * @hide
+         */
+        public void copyFrom(RecentsActivityValues v) {
+            if (v != null) {
+                label = v.label;
+                icon = v.icon;
+                colorPrimary = v.colorPrimary;
+            }
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            TextUtils.writeToParcel(label, dest,
+                    Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+            if (icon == null) {
+                dest.writeInt(0);
+            } else {
+                dest.writeInt(1);
+                icon.writeToParcel(dest, 0);
+            }
+            dest.writeInt(colorPrimary);
+        }
+
+        public void readFromParcel(Parcel source) {
+            label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+            icon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null;
+            colorPrimary = source.readInt();
+        }
+
+        public static final Creator<RecentsActivityValues> CREATOR
+                = new Creator<RecentsActivityValues>() {
+            public RecentsActivityValues createFromParcel(Parcel source) {
+                return new RecentsActivityValues(source);
+            }
+            public RecentsActivityValues[] newArray(int size) {
+                return new RecentsActivityValues[size];
+            }
+        };
+
+        @Override
+        public String toString() {
+            return "RecentsActivityValues Label: " + label + " Icon: " + icon +
+                    " colorPrimary: " + colorPrimary;
+        }
+    }
+
+    /**
      * Information you can retrieve about tasks that the user has most recently
      * started or visited.
      */
@@ -523,16 +628,10 @@
         public int userId;
 
         /**
-         * The label of the highest activity in the task stack to have set a label using
-         * {@link Activity#setActivityLabelAndIcon(CharSequence, android.graphics.Bitmap)}.
+         * The recent activity values for the highest activity in the stack to have set the values.
+         * {@link Activity#setRecentsActivityValues(android.app.ActivityManager.RecentsActivityValues)}.
          */
-        public CharSequence activityLabel;
-
-        /**
-         * The Bitmap icon of the highest activity in the task stack to set a Bitmap using
-         * {@link Activity#setActivityLabelAndIcon(CharSequence, android.graphics.Bitmap)}.
-         */
-        public Bitmap activityIcon;
+        public RecentsActivityValues activityValues;
 
         public RecentTaskInfo() {
         }
@@ -555,13 +654,11 @@
             ComponentName.writeToParcel(origActivity, dest);
             TextUtils.writeToParcel(description, dest,
                     Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            TextUtils.writeToParcel(activityLabel, dest,
-                    Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            if (activityIcon == null) {
-                dest.writeInt(0);
-            } else {
+            if (activityValues != null) {
                 dest.writeInt(1);
-                activityIcon.writeToParcel(dest, 0);
+                activityValues.writeToParcel(dest, 0);
+            } else {
+                dest.writeInt(0);
             }
             dest.writeInt(stackId);
             dest.writeInt(userId);
@@ -573,8 +670,8 @@
             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);
-            activityIcon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null;
+            activityValues = source.readInt() > 0 ?
+                    RecentsActivityValues.CREATOR.createFromParcel(source) : null;
             stackId = source.readInt();
             userId = source.readInt();
         }
@@ -791,42 +888,6 @@
      * activity -- the task may have been frozen by the system, so that it
      * can be restarted in its previous state when next brought to the
      * foreground.
-     * 
-     * @param maxNum The maximum number of entries to return in the list.  The
-     * actual number returned may be smaller, depending on how many tasks the
-     * user has started.
-     *
-     * @param flags Optional flags
-     * @param receiver Optional receiver for delayed thumbnails
-     *
-     * @return Returns a list of RunningTaskInfo records describing each of
-     * the running tasks.
-     * 
-     * Some thumbnails may not be available at the time of this call. The optional
-     * receiver may be used to receive those thumbnails.
-     *
-     * @throws SecurityException Throws SecurityException if the caller does
-     * not hold the {@link android.Manifest.permission#GET_TASKS} permission.
-     *
-     * @hide
-     */
-    public List<RunningTaskInfo> getRunningTasks(int maxNum, int flags, IThumbnailReceiver receiver)
-            throws SecurityException {
-        try {
-            return ActivityManagerNative.getDefault().getTasks(maxNum, flags, receiver);
-        } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return null;
-        }
-    }
-
-    /**
-     * Return a list of the tasks that are currently running, with
-     * the most recent being first and older ones after in order.  Note that
-     * "running" does not mean any of the task's code is currently loaded or
-     * activity -- the task may have been frozen by the system, so that it
-     * can be restarted in its previous state when next brought to the
-     * foreground.
      *
      * <p><b>Note: this method is only intended for debugging and presenting
      * task management user interfaces</b>.  This should never be used for
@@ -849,7 +910,12 @@
      */
     public List<RunningTaskInfo> getRunningTasks(int maxNum)
             throws SecurityException {
-        return getRunningTasks(maxNum, 0, null);
+        try {
+            return ActivityManagerNative.getDefault().getTasks(maxNum, 0);
+        } catch (RemoteException e) {
+            // System dead, we will be dead too soon!
+            return null;
+        }
     }
 
     /**
@@ -1627,13 +1693,6 @@
         public int lastTrimLevel;
 
         /**
-         * Constant for {@link #importance}: this is a persistent process.
-         * Only used when reporting to process observers.
-         * @hide
-         */
-        public static final int IMPORTANCE_PERSISTENT = 50;
-
-        /**
          * Constant for {@link #importance}: this process is running the
          * foreground UI.
          */
@@ -1748,9 +1807,16 @@
          */
         public int importanceReasonImportance;
 
+        /**
+         * Current process state, as per PROCESS_STATE_* constants.
+         * @hide
+         */
+        public int processState;
+
         public RunningAppProcessInfo() {
             importance = IMPORTANCE_FOREGROUND;
             importanceReasonCode = REASON_UNKNOWN;
+            processState = PROCESS_STATE_IMPORTANT_FOREGROUND;
         }
         
         public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) {
@@ -1776,6 +1842,7 @@
             dest.writeInt(importanceReasonPid);
             ComponentName.writeToParcel(importanceReasonComponent, dest);
             dest.writeInt(importanceReasonImportance);
+            dest.writeInt(processState);
         }
 
         public void readFromParcel(Parcel source) {
@@ -1791,6 +1858,7 @@
             importanceReasonPid = source.readInt();
             importanceReasonComponent = ComponentName.readFromParcel(source);
             importanceReasonImportance = source.readInt();
+            processState = source.readInt();
         }
 
         public static final Creator<RunningAppProcessInfo> CREATOR = 
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b1c37de..57da21e 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -509,11 +509,7 @@
             data.enforceInterface(IActivityManager.descriptor);
             int maxNum = data.readInt();
             int fl = data.readInt();
-            IBinder receiverBinder = data.readStrongBinder();
-            IThumbnailReceiver receiver = receiverBinder != null
-                ? IThumbnailReceiver.Stub.asInterface(receiverBinder)
-                : null;
-            List<ActivityManager.RunningTaskInfo> list = getTasks(maxNum, fl, receiver);
+            List<ActivityManager.RunningTaskInfo> list = getTasks(maxNum, fl);
             reply.writeNoException();
             int N = list != null ? list.size() : -1;
             reply.writeInt(N);
@@ -712,17 +708,6 @@
             return true;
         }
 
-        case REPORT_THUMBNAIL_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Bitmap thumbnail = data.readInt() != 0
-                ? Bitmap.CREATOR.createFromParcel(data) : null;
-            CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
-            reportThumbnail(token, thumbnail, description);
-            reply.writeNoException();
-            return true;
-        }
-
         case GET_CONTENT_PROVIDER_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder b = data.readStrongBinder();
@@ -2134,13 +2119,12 @@
             return true;
         }
 
-        case SET_ACTIVITY_LABEL_ICON_TRANSACTION: {
+        case SET_RECENTS_ACTIVITY_VALUES_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            CharSequence activityLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
-            Bitmap activityIcon = data.readInt() > 0
-                    ? Bitmap.CREATOR.createFromParcel(data) : null;
-            setActivityLabelAndIcon(token, activityLabel, activityIcon);
+            ActivityManager.RecentsActivityValues values =
+                    ActivityManager.RecentsActivityValues.CREATOR.createFromParcel(data);
+            setRecentsActivityValues(token, values);
             reply.writeNoException();
             return true;
         }
@@ -2678,14 +2662,12 @@
         reply.recycle();
         return res;
     }
-    public List getTasks(int maxNum, int flags,
-            IThumbnailReceiver receiver) throws RemoteException {
+    public List getTasks(int maxNum, int flags) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(maxNum);
         data.writeInt(flags);
-        data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
         mRemote.transact(GET_TASKS_TRANSACTION, data, reply, 0);
         reply.readException();
         ArrayList list = null;
@@ -2964,25 +2946,6 @@
         reply.recycle();
         return res;
     }
-    public void reportThumbnail(IBinder token,
-                                Bitmap thumbnail, CharSequence description) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        if (thumbnail != null) {
-            data.writeInt(1);
-            thumbnail.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        TextUtils.writeToParcel(description, data, 0);
-        mRemote.transact(REPORT_THUMBNAIL_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
     public ContentProviderHolder getContentProvider(IApplicationThread caller,
             String name, int userId, boolean stable) throws RemoteException {
         Parcel data = Parcel.obtain();
@@ -4919,21 +4882,14 @@
     }
 
     @Override
-    public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
-            Bitmap activityIcon) throws RemoteException
-    {
+    public void setRecentsActivityValues(IBinder token, ActivityManager.RecentsActivityValues values)
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        TextUtils.writeToParcel(activityLabel, data, 0);
-        if (activityIcon != null) {
-            data.writeInt(1);
-            activityIcon.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(SET_ACTIVITY_LABEL_ICON_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        values.writeToParcel(data, 0);
+        mRemote.transact(SET_RECENTS_ACTIVITY_VALUES_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
         reply.readException();
         data.recycle();
         reply.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7dc21b4..3b2ff7f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -821,10 +821,6 @@
             sendMessage(H.SUICIDE, null);
         }
 
-        public void requestThumbnail(IBinder token) {
-            sendMessage(H.REQUEST_THUMBNAIL, token);
-        }
-
         public void scheduleConfigurationChanged(Configuration config) {
             updatePendingConfiguration(config);
             sendMessage(H.CONFIGURATION_CHANGED, config);
@@ -1168,7 +1164,7 @@
         public static final int CREATE_SERVICE          = 114;
         public static final int SERVICE_ARGS            = 115;
         public static final int STOP_SERVICE            = 116;
-        public static final int REQUEST_THUMBNAIL       = 117;
+
         public static final int CONFIGURATION_CHANGED   = 118;
         public static final int CLEAN_UP_CONTEXT        = 119;
         public static final int GC_WHEN_IDLE            = 120;
@@ -1218,7 +1214,6 @@
                     case CREATE_SERVICE: return "CREATE_SERVICE";
                     case SERVICE_ARGS: return "SERVICE_ARGS";
                     case STOP_SERVICE: return "STOP_SERVICE";
-                    case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
                     case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
                     case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
                     case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
@@ -1367,11 +1362,6 @@
                     maybeSnapshot();
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
-                case REQUEST_THUMBNAIL:
-                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestThumbnail");
-                    handleRequestThumbnail((IBinder)msg.obj);
-                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-                    break;
                 case CONFIGURATION_CHANGED:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
                     mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
@@ -3817,28 +3807,6 @@
         handleLaunchActivity(r, currentIntent);
     }
 
-    private void handleRequestThumbnail(IBinder token) {
-        ActivityClientRecord r = mActivities.get(token);
-        Bitmap thumbnail = createThumbnailBitmap(r);
-        CharSequence description = null;
-        try {
-            description = r.activity.onCreateDescription();
-        } catch (Exception e) {
-            if (!mInstrumentation.onException(r.activity, e)) {
-                throw new RuntimeException(
-                        "Unable to create description of activity "
-                        + r.intent.getComponent().toShortString()
-                        + ": " + e.toString(), e);
-            }
-        }
-        //System.out.println("Reporting top thumbnail " + thumbnail);
-        try {
-            ActivityManagerNative.getDefault().reportThumbnail(
-                token, thumbnail, description);
-        } catch (RemoteException ex) {
-        }
-    }
-
     ArrayList<ComponentCallbacks2> collectComponentCallbacks(
             boolean allActivities, Configuration newConfig) {
         ArrayList<ComponentCallbacks2> callbacks
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index f96c3e3..3c1455b 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -206,6 +206,7 @@
     private ResultReceiver mRemoteResultReceiver;
     private boolean mNotifiedSharedElementTransitionComplete;
     private boolean mNotifiedExitTransitionComplete;
+    private boolean mSharedElementTransitionStarted;
 
     private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
 
@@ -250,7 +251,11 @@
                 onPrepareRestore();
                 break;
             case MSG_EXIT_TRANSITION_COMPLETE:
-                onRemoteSceneExitComplete();
+                if (!mSharedElementTransitionStarted) {
+                    send(resultCode, resultData);
+                } else {
+                    onRemoteSceneExitComplete();
+                }
                 break;
             case MSG_TAKE_SHARED_ELEMENTS:
                 ArrayList<String> sharedElementNames
@@ -456,9 +461,13 @@
         mTargetSharedNames.clear();
         if (sharedElements == null) {
             ArrayMap<String, View> map = new ArrayMap<String, View>();
-            setViewVisibility(mEnteringViews, View.VISIBLE);
+            if (getViewsTransition() != null) {
+                setViewVisibility(mEnteringViews, View.VISIBLE);
+            }
             getDecor().findSharedElements(map);
-            setViewVisibility(mEnteringViews, View.INVISIBLE);
+            if (getViewsTransition() != null) {
+                setViewVisibility(mEnteringViews, View.INVISIBLE);
+            }
             for (int i = 0; i < map.size(); i++) {
                 View view = map.valueAt(i);
                 String name = map.keyAt(i);
@@ -582,6 +591,7 @@
                         getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
                         mListener.onCaptureSharedElementEnd(mTargetSharedNames, mSharedElements,
                                 acceptedOverlayViews);
+                        mSharedElementTransitionStarted = true;
                         return true;
                     }
                 }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index fcc7f8e..7f2fb59 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -312,14 +312,6 @@
             return true;
         }
 
-        case REQUEST_THUMBNAIL_TRANSACTION:
-        {
-            data.enforceInterface(IApplicationThread.descriptor);
-            IBinder b = data.readStrongBinder();
-            requestThumbnail(b);
-            return true;
-        }
-
         case SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION:
         {
             data.enforceInterface(IApplicationThread.descriptor);
@@ -986,16 +978,6 @@
         data.recycle();
     }
 
-    public final void requestThumbnail(IBinder token)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        data.writeInterfaceToken(IApplicationThread.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(REQUEST_THUMBNAIL_TRANSACTION, data, null,
-                IBinder.FLAG_ONEWAY);
-        data.recycle();
-    }
-
     public final void scheduleConfigurationChanged(Configuration config)
             throws RemoteException {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index fe532bf..a4b2651 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -473,14 +473,14 @@
         registerService(NOTIFICATION_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     final Context outerContext = ctx.getOuterContext();
+                    // TODO: Why are we not just using the theme attribute
+                    // that defines the dialog theme?
                     return new NotificationManager(
                         new ContextThemeWrapper(outerContext,
-                                Resources.selectSystemTheme(0,
+                                outerContext.getResources().selectSystemTheme(0,
                                         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_Light_Dialog)),
+                                        com.android.internal.R.array.system_theme_sdks,
+                                        com.android.internal.R.array.system_theme_dialog_styles)),
                         ctx.mMainThread.getHandler());
                 }});
 
@@ -731,7 +731,7 @@
     @Override
     public Resources.Theme getTheme() {
         if (mTheme == null) {
-            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
+            mThemeResource = mResources.selectDefaultTheme(mThemeResource,
                     getOuterContext().getApplicationInfo().targetSdkVersion);
             mTheme = mResources.newTheme();
             mTheme.applyStyle(mThemeResource, true);
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 0798529..cbb8359 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -23,8 +23,6 @@
 import android.os.Bundle;
 import android.os.ResultReceiver;
 import android.transition.Transition;
-import android.util.ArrayMap;
-import android.util.Pair;
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.Window;
@@ -135,11 +133,6 @@
     }
 
     @Override
-    protected void onRemoteSceneExitComplete() {
-        super.onRemoteSceneExitComplete();
-    }
-
-    @Override
     protected void onTakeSharedElements(ArrayList<String> sharedElementNames, Bundle state) {
         mEnteringSharedElementNames = new ArrayList<String>();
         mEnteringSharedElementNames.addAll(sharedElementNames);
@@ -149,6 +142,7 @@
     @Override
     protected void sharedElementTransitionComplete(Bundle bundle) {
         notifySharedElementTransitionComplete(bundle);
+        exitAfterSharedElementTransition();
     }
 
     @Override
@@ -223,6 +217,7 @@
 
     @Override
     protected void startExitTransition(ArrayList<String> sharedElements) {
+        mMakeOpaque = false;
         notifyPrepareRestore();
 
         if (getDecor().getBackground() == null) {
@@ -280,7 +275,7 @@
     }
 
     private void exitAfterSharedElementTransition() {
-        if (mSharedElementTransitionComplete && mExitTransitionComplete) {
+        if (mSharedElementTransitionComplete && mExitTransitionComplete && mBackgroundFadedOut) {
             mActivity.finish();
             if (mSupportsTransition) {
                 mActivity.overridePendingTransition(0, 0);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 6b94c4e..2e9cdf3b7 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -111,8 +111,7 @@
     public void activityDestroyed(IBinder token) throws RemoteException;
     public String getCallingPackage(IBinder token) throws RemoteException;
     public ComponentName getCallingActivity(IBinder token) throws RemoteException;
-    public List<RunningTaskInfo> getTasks(int maxNum, int flags,
-                         IThumbnailReceiver receiver) throws RemoteException;
+    public List<RunningTaskInfo> getTasks(int maxNum, int flags) throws RemoteException;
     public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
             int flags, int userId) throws RemoteException;
     public ActivityManager.TaskThumbnails getTaskThumbnails(int taskId) throws RemoteException;
@@ -131,9 +130,6 @@
     public boolean isInHomeStack(int taskId) throws RemoteException;
     public void setFocusedStack(int stackId) throws RemoteException;
     public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException;
-    /* oneway */
-    public void reportThumbnail(IBinder token,
-            Bitmap thumbnail, CharSequence description) throws RemoteException;
     public ContentProviderHolder getContentProvider(IApplicationThread caller,
             String name, int userId, boolean stable) throws RemoteException;
     public ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token)
@@ -439,8 +435,8 @@
     public boolean isInLockTaskMode() throws RemoteException;
 
     /** @hide */
-    public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
-            Bitmap activityBitmap) throws RemoteException;
+    public void setRecentsActivityValues(IBinder token, ActivityManager.RecentsActivityValues values)
+            throws RemoteException;
 
     /*
      * Private non-Binder interfaces
@@ -571,7 +567,7 @@
     int MOVE_TASK_TO_BACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+24;
     int MOVE_TASK_BACKWARDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25;
     int GET_TASK_FOR_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26;
-    int REPORT_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+27;
+
     int GET_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28;
     int PUBLISH_CONTENT_PROVIDERS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
     int REF_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
@@ -738,6 +734,6 @@
     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_ACTIVITY_LABEL_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217;
+    int SET_RECENTS_ACTIVITY_VALUES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217;
     int START_VOICE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+218;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index f290e94..fefba8a 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -101,7 +101,6 @@
             Bundle coreSettings) throws RemoteException;
     void scheduleExit() throws RemoteException;
     void scheduleSuicide() throws RemoteException;
-    void requestThumbnail(IBinder token) throws RemoteException;
     void scheduleConfigurationChanged(Configuration config) throws RemoteException;
     void updateTimeZone() throws RemoteException;
     void clearDnsCache() throws RemoteException;
@@ -159,7 +158,7 @@
     int SCHEDULE_STOP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+11;
     int BIND_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+12;
     int SCHEDULE_EXIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+13;
-    int REQUEST_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+14;
+
     int SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+15;
     int SCHEDULE_SERVICE_ARGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+16;
     int UPDATE_TIME_ZONE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+17;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index ad4027d..b917263 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -58,6 +58,8 @@
     ZenModeConfig getZenModeConfig();
     boolean setZenModeConfig(in ZenModeConfig config);
     oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
-    oneway void requestZenModeConditions(in IConditionListener callback, boolean requested);
+    oneway void requestZenModeConditions(in IConditionListener callback, int relevance);
     oneway void setZenModeCondition(in Uri conditionId);
+    oneway void setAutomaticZenModeConditions(in Uri[] conditionIds);
+    Condition[] getAutomaticZenModeConditions();
 }
\ No newline at end of file
diff --git a/core/java/android/app/IProcessObserver.aidl b/core/java/android/app/IProcessObserver.aidl
index e587912..ecf2c73 100644
--- a/core/java/android/app/IProcessObserver.aidl
+++ b/core/java/android/app/IProcessObserver.aidl
@@ -20,7 +20,7 @@
 oneway interface IProcessObserver {
 
     void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities);
-    void onImportanceChanged(int pid, int uid, int importance);
+    void onProcessStateChanged(int pid, int uid, int procState);
     void onProcessDied(int pid, int uid);
 
 }
diff --git a/core/java/android/app/IThumbnailReceiver.aidl b/core/java/android/app/IThumbnailReceiver.aidl
deleted file mode 100644
index 7943f2c..0000000
--- a/core/java/android/app/IThumbnailReceiver.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/* //device/java/android/android/app/IThumbnailReceiver.aidl
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-package android.app;
-
-import android.graphics.Bitmap;
-
-/**
- * System private API for receiving updated thumbnails from a checkpoint.
- *
- * {@hide}
- */
-oneway interface IThumbnailReceiver {
-    void newThumbnail(int id, in Bitmap thumbnail, CharSequence description);
-    void finished();
-}
-
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 5cf61a8..ce5306f 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -60,6 +60,7 @@
             | DISABLE_SEARCH;
 
     public static final int NAVIGATION_HINT_BACK_ALT      = 1 << 0;
+    public static final int NAVIGATION_HINT_IME_SHOWN     = 1 << 1;
 
     public static final int WINDOW_STATUS_BAR = 1;
     public static final int WINDOW_NAVIGATION_BAR = 2;
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 5f8ebbe..58d707c 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -651,6 +651,10 @@
      *         not "image/*"
      */
     public Intent getCropAndSetWallpaperIntent(Uri imageUri) {
+        if (imageUri == null) {
+            throw new IllegalArgumentException("Image URI must not be null");
+        }
+
         if (!ContentResolver.SCHEME_CONTENT.equals(imageUri.getScheme())) {
             throw new IllegalArgumentException("Image URI must be of the "
                     + ContentResolver.SCHEME_CONTENT + " scheme type");
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 68ab611..6f68dfb 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -172,6 +172,16 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_SET_NEW_PASSWORD
             = "android.app.action.SET_NEW_PASSWORD";
+    /**
+     * Flag for {@link #forwardMatchingIntents}: the intents will forwarded to the primary user.
+     */
+    public static int FLAG_TO_PRIMARY_USER = 0x0001;
+
+    /**
+     * Flag for {@link #forwardMatchingIntents}: the intents will be forwarded to the managed
+     * profile.
+     */
+    public static int FLAG_TO_MANAGED_PROFILE = 0x0002;
 
     /**
      * Return true if the given administrator component is currently
@@ -1778,7 +1788,7 @@
      * Sets the enabled state of the profile. A profile should be enabled only once it is ready to
      * be used. Only the profile owner can call this.
      *
-     * @see #isPRofileOwnerApp
+     * @see #isProfileOwnerApp
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      */
@@ -1834,27 +1844,6 @@
 
     /**
      * @hide
-     * @param userId the userId of a managed profile profile.
-     *
-     * @return whether or not the managed profile is enabled.
-     * @throws IllegalArgumentException if the userId is invalid.
-     */
-    public boolean isProfileEnabled(int userId) throws IllegalArgumentException {
-        if (mService != null) {
-            try {
-                return mService.isProfileEnabled(userId);
-            } catch (RemoteException re) {
-                Log.w(TAG, "Failed to get status for owner profile.");
-                throw new IllegalArgumentException(
-                        "Failed to get status for owner profile.", re);
-            }
-        }
-        return true;
-    }
-
-
-    /**
-     * @hide
      * @return the human readable name of the organisation associated with this DPM or null if
      *         one is not set.
      * @throws IllegalArgumentException if the userId is invalid.
@@ -1953,6 +1942,39 @@
     }
 
     /**
+     * Called by a profile owner to forward intents sent from the managed profile to the owner, or
+     * from the owner to the managed profile.
+     * If an intent matches this intent filter, then activities belonging to the other user can
+     * respond to this intent.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param filter if an intent matches this IntentFilter, then it can be forwarded.
+     */
+    public void forwardMatchingIntents(ComponentName admin, IntentFilter filter, int flags) {
+        if (mService != null) {
+            try {
+                mService.forwardMatchingIntents(admin, filter, flags);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Called by a profile owner to remove all the forwarding intent filters from the current user
+     * and from the owner.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     */
+    public void clearForwardingIntentFilters(ComponentName admin) {
+        if (mService != null) {
+            try {
+                mService.clearForwardingIntentFilters(admin);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
      * Called by a profile or device owner to get the application restrictions for a given target
      * application running in the managed profile.
      *
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 72b3c20..495a5f9 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -109,7 +109,6 @@
     String getProfileOwner(int userHandle);
     String getProfileOwnerName(int userHandle);
     void setProfileEnabled(in ComponentName who);
-    boolean isProfileEnabled(int userHandle);
 
     boolean installCaCert(in byte[] certBuffer);
     void uninstallCaCert(in byte[] certBuffer);
@@ -121,4 +120,6 @@
     Bundle getApplicationRestrictions(in ComponentName who, in String packageName);
 
     void setUserRestriction(in ComponentName who, in String key, boolean enable);
+    void forwardMatchingIntents(in ComponentName admin, in IntentFilter filter, int flags);
+    void clearForwardingIntentFilters(in ComponentName admin);
 }
diff --git a/core/java/android/app/task/ITaskCallback.aidl b/core/java/android/app/task/ITaskCallback.aidl
new file mode 100644
index 0000000..ffa57d1
--- /dev/null
+++ b/core/java/android/app/task/ITaskCallback.aidl
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.task;
+
+import android.app.task.ITaskService;
+import android.app.task.TaskParams;
+
+/**
+ * The server side of the TaskManager IPC protocols.  The app-side implementation
+ * invokes on this interface to indicate completion of the (asynchronous) instructions
+ * issued by the server.
+ *
+ * In all cases, the 'who' parameter is the caller's service binder, used to track
+ * which Task Service instance is reporting.
+ *
+ * {@hide}
+ */
+interface ITaskCallback {
+    /**
+     * Immediate callback to the system after sending a start signal, used to quickly detect ANR.
+     *
+     * @param taskId Unique integer used to identify this task.
+     */
+    void acknowledgeStartMessage(int taskId);
+    /**
+     * Immediate callback to the system after sending a stop signal, used to quickly detect ANR.
+     *
+     * @param taskId Unique integer used to identify this task.
+     */
+    void acknowledgeStopMessage(int taskId);
+    /*
+     * Tell the task manager that the client is done with its execution, so that it can go on to
+     * the next one and stop attributing wakelock time to us etc.
+     *
+     * @param taskId Unique integer used to identify this task.
+     * @param reschedule Whether or not to reschedule this task.
+     */
+    void taskFinished(int taskId, boolean reschedule);
+}
diff --git a/core/java/android/app/task/ITaskService.aidl b/core/java/android/app/task/ITaskService.aidl
new file mode 100644
index 0000000..87b0191
--- /dev/null
+++ b/core/java/android/app/task/ITaskService.aidl
@@ -0,0 +1,35 @@
+/**
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.task;
+
+import android.app.task.ITaskCallback;
+import android.app.task.TaskParams;
+
+import android.os.Bundle;
+
+/**
+ * Interface that the framework uses to communicate with application code that implements a
+ * TaskService.  End user code does not implement this interface directly; instead, the app's
+ * service implementation will extend android.app.task.TaskService.
+ * {@hide}
+ */
+oneway interface ITaskService {
+    /** Begin execution of application's task. */
+    void startTask(in TaskParams taskParams);
+    /** Stop execution of application's task. */
+    void stopTask(in TaskParams taskParams);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/app/task/TaskParams.aidl
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/app/task/TaskParams.aidl
index 0377123..9b25855 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/app/task/TaskParams.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
+/**
+ * Copyright 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
+ *     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,
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.app.task;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+parcelable TaskParams;
\ No newline at end of file
diff --git a/core/java/android/app/task/TaskParams.java b/core/java/android/app/task/TaskParams.java
new file mode 100644
index 0000000..e2eafd8
--- /dev/null
+++ b/core/java/android/app/task/TaskParams.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app.task;
+
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Contains the parameters used to configure/identify your task. You do not create this object
+ * yourself, instead it is handed in to your application by the System.
+ */
+public class TaskParams implements Parcelable {
+
+    private final int taskId;
+    private final Bundle extras;
+    private final IBinder mCallback;
+
+    /**
+     * @return The unique id of this task, specified at creation time.
+     */
+    public int getTaskId() {
+        return taskId;
+    }
+
+    /**
+     * @return The extras you passed in when constructing this task with
+     * {@link android.content.Task.Builder#setExtras(android.os.Bundle)}. This will
+     * never be null. If you did not set any extras this will be an empty bundle.
+     */
+    public Bundle getExtras() {
+        return extras;
+    }
+
+    /**
+     * @hide
+     */
+    public ITaskCallback getCallback() {
+        return ITaskCallback.Stub.asInterface(mCallback);
+    }
+
+    private TaskParams(Parcel in) {
+        taskId = in.readInt();
+        extras = in.readBundle();
+        mCallback = in.readStrongBinder();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(taskId);
+        dest.writeBundle(extras);
+        dest.writeStrongBinder(mCallback);
+    }
+
+    public static final Creator<TaskParams> CREATOR = new Creator<TaskParams>() {
+        @Override
+        public TaskParams createFromParcel(Parcel in) {
+            return new TaskParams(in);
+        }
+
+        @Override
+        public TaskParams[] newArray(int size) {
+            return new TaskParams[size];
+        }
+    };
+}
diff --git a/core/java/android/app/task/TaskService.java b/core/java/android/app/task/TaskService.java
new file mode 100644
index 0000000..81333be
--- /dev/null
+++ b/core/java/android/app/task/TaskService.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app.task;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * <p>Entry point for the callback from the {@link android.content.TaskManager}.</p>
+ * <p>This is the base class that handles asynchronous requests that were previously scheduled. You
+ * are responsible for overriding {@link TaskService#onStartTask(TaskParams)}, which is where
+ * you will implement your task logic.</p>
+ * <p>This service executes each incoming task on a {@link android.os.Handler} running on your
+ * application's main thread. This means that you <b>must</b> offload your execution logic to
+ * another thread/handler/{@link android.os.AsyncTask} of your choosing. Not doing so will result
+ * in blocking any future callbacks from the TaskManager - specifically
+ * {@link #onStopTask(android.app.task.TaskParams)}, which is meant to inform you that the
+ * scheduling requirements are no longer being met.</p>
+ */
+public abstract class TaskService extends Service {
+    private static final String TAG = "TaskService";
+
+    /**
+     * Task services must be protected with this permission:
+     *
+     * <pre class="prettyprint">
+     *     <service android:name="MyTaskService"
+     *              android:permission="android.permission.BIND_TASK_SERVICE" >
+     *         ...
+     *     </service>
+     * </pre>
+     *
+     * <p>If a task service is declared in the manifest but not protected with this
+     * permission, that service will be ignored by the OS.
+     */
+    public static final String PERMISSION_BIND =
+            "android.permission.BIND_TASK_SERVICE";
+
+    /**
+     * Identifier for a message that will result in a call to
+     * {@link #onStartTask(android.app.task.TaskParams)}.
+     */
+    private final int MSG_EXECUTE_TASK = 0;
+    /**
+     * Message that will result in a call to {@link #onStopTask(android.app.task.TaskParams)}.
+     */
+    private final int MSG_STOP_TASK = 1;
+    /**
+     * Message that the client has completed execution of this task.
+     */
+    private final int MSG_TASK_FINISHED = 2;
+
+    /** Lock object for {@link #mHandler}. */
+    private final Object mHandlerLock = new Object();
+
+    /**
+     * Handler we post tasks to. Responsible for calling into the client logic, and handling the
+     * callback to the system.
+     */
+    @GuardedBy("mHandlerLock")
+    TaskHandler mHandler;
+
+    /** Binder for this service. */
+    ITaskService mBinder = new ITaskService.Stub() {
+        @Override
+        public void startTask(TaskParams taskParams) {
+            ensureHandler();
+            Message m = Message.obtain(mHandler, MSG_EXECUTE_TASK, taskParams);
+            m.sendToTarget();
+        }
+        @Override
+        public void stopTask(TaskParams taskParams) {
+            ensureHandler();
+            Message m = Message.obtain(mHandler, MSG_STOP_TASK, taskParams);
+            m.sendToTarget();
+        }
+    };
+
+    /** @hide */
+    void ensureHandler() {
+        synchronized (mHandlerLock) {
+            if (mHandler == null) {
+                mHandler = new TaskHandler(getMainLooper());
+            }
+        }
+    }
+
+    /**
+     * Runs on application's main thread - callbacks are meant to offboard work to some other
+     * (app-specified) mechanism.
+     * @hide
+     */
+    class TaskHandler extends Handler {
+        TaskHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            final TaskParams params = (TaskParams) msg.obj;
+            switch (msg.what) {
+                case MSG_EXECUTE_TASK:
+                    try {
+                        TaskService.this.onStartTask(params);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Error while executing task: " + params.getTaskId());
+                        throw new RuntimeException(e);
+                    } finally {
+                        maybeAckMessageReceived(params, MSG_EXECUTE_TASK);
+                    }
+                    break;
+                case MSG_STOP_TASK:
+                    try {
+                        TaskService.this.onStopTask(params);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Application unable to handle onStopTask.", e);
+                        throw new RuntimeException(e);
+                    } finally {
+                        maybeAckMessageReceived(params, MSG_STOP_TASK);
+                    }
+                    break;
+                case MSG_TASK_FINISHED:
+                    final boolean needsReschedule = (msg.arg2 == 1);
+                    ITaskCallback callback = params.getCallback();
+                    if (callback != null) {
+                        try {
+                            callback.taskFinished(params.getTaskId(), needsReschedule);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Error reporting task finish to system: binder has gone" +
+                                    "away.");
+                        }
+                    } else {
+                        Log.e(TAG, "finishTask() called for a nonexistent task id.");
+                    }
+                    break;
+                default:
+                    Log.e(TAG, "Unrecognised message received.");
+                    break;
+            }
+        }
+
+        /**
+         * Messages come in on the application's main thread, so rather than run the risk of
+         * waiting for an app that may be doing something foolhardy, we ack to the system after
+         * processing a message. This allows us to throw up an ANR dialogue as quickly as possible.
+         * @param params id of the task we're acking.
+         * @param state Information about what message we're acking.
+         */
+        private void maybeAckMessageReceived(TaskParams params, int state) {
+            final ITaskCallback callback = params.getCallback();
+            final int taskId = params.getTaskId();
+            if (callback != null) {
+                try {
+                    if (state == MSG_EXECUTE_TASK) {
+                        callback.acknowledgeStartMessage(taskId);
+                    } else if (state == MSG_STOP_TASK) {
+                        callback.acknowledgeStopMessage(taskId);
+                    }
+                } catch(RemoteException e) {
+                    Log.e(TAG, "System unreachable for starting task.");
+                }
+            } else {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, state + ": Attempting to ack a task that has already been" +
+                            "processed.");
+                }
+            }
+        }
+    }
+
+    /** @hide */
+    public final IBinder onBind(Intent intent) {
+        return mBinder.asBinder();
+    }
+
+    /**
+     * Override this method with the callback logic for your task. Any such logic needs to be
+     * performed on a separate thread, as this function is executed on your application's main
+     * thread.
+     *
+     * @param params Parameters specifying info about this task, including the extras bundle you
+     *               optionally provided at task-creation time.
+     */
+    public abstract void onStartTask(TaskParams params);
+
+    /**
+     * This method is called if your task should be stopped even before you've called
+     * {@link #taskFinished(TaskParams, boolean)}.
+     *
+     * <p>This will happen if the requirements specified at schedule time are no longer met. For
+     * example you may have requested WiFi with
+     * {@link android.content.Task.Builder#setRequiredNetworkCapabilities(int)}, yet while your
+     * task was executing the user toggled WiFi. Another example is if you had specified
+     * {@link android.content.Task.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its
+     * idle maintenance window. You are solely responsible for the behaviour of your application
+     * upon receipt of this message; your app will likely start to misbehave if you ignore it. One
+     * repercussion is that the system will cease to hold a wakelock for you.</p>
+     *
+     * <p>After you've done your clean-up you are still expected to call
+     * {@link #taskFinished(TaskParams, boolean)} this will inform the TaskManager that all is well, and
+     * allow you to reschedule your task as it is probably uncompleted. Until you call
+     * taskFinished() you will not receive any newly scheduled tasks with the given task id as the
+     * TaskManager will consider the task to be in an error state.</p>
+     *
+     * @param params Parameters specifying info about this task.
+     * @return True to indicate to the TaskManager whether you'd like to reschedule this task based
+     * on the criteria provided at task creation-time. False to drop the task. Regardless of the
+     * value returned, your task must stop executing.
+     */
+    public abstract boolean onStopTask(TaskParams params);
+
+    /**
+     * Callback to inform the TaskManager you have completed execution. This can be called from any
+     * thread, as it will ultimately be run on your application's main thread. When the system
+     * receives this message it will release the wakelock being held.
+     * <p>
+     *     You can specify post-execution behaviour to the scheduler here with <code>needsReschedule
+     *     </code>. This will apply a back-off timer to your task based on the default, or what was
+     *     set with {@link android.content.Task.Builder#setBackoffCriteria(long, int)}. The
+     *     original requirements are always honoured even for a backed-off task.
+     *     Note that a task running in idle mode will not be backed-off. Instead what will happen
+     *     is the task will be re-added to the queue and re-executed within a future idle
+     *     maintenance window.
+     * </p>
+     *
+     * @param params Parameters specifying system-provided info about this task, this was given to
+     *               your application in {@link #onStartTask(TaskParams)}.
+     * @param needsReschedule True if this task is complete, false if you want the TaskManager to
+     *                        reschedule you.
+     */
+    public final void taskFinished(TaskParams params, boolean needsReschedule) {
+        ensureHandler();
+        Message m = Message.obtain(mHandler, MSG_TASK_FINISHED, params);
+        m.arg2 = needsReschedule ? 1 : 0;
+        m.sendToTarget();
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 4b33799..8670da7 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -54,6 +54,12 @@
     public static final int WIDGET_CATEGORY_KEYGUARD = 2;
 
     /**
+     * Indicates that the widget can be displayed within recents.
+     * @hide
+     */
+    public static final int WIDGET_CATEGORY_RECENTS = 4;
+
+    /**
      * Identity of this AppWidget component.  This component should be a {@link
      * android.content.BroadcastReceiver}, and it will be sent the AppWidget intents
      * {@link android.appwidget as described in the AppWidget package documentation}.
diff --git a/core/java/android/content/Task.java b/core/java/android/content/Task.java
new file mode 100644
index 0000000..ed5ed884
--- /dev/null
+++ b/core/java/android/content/Task.java
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.content;
+
+import android.app.task.TaskService;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Container of data passed to the {@link android.content.TaskManager} fully encapsulating the
+ * parameters required to schedule work against the calling application. These are constructed
+ * using the {@link Task.Builder}.
+ */
+public class Task implements Parcelable {
+
+    public interface NetworkType {
+        public final int ANY = 0;
+        public final int UNMETERED = 1;
+    }
+
+    /**
+     * Linear: retry_time(failure_time, t) = failure_time + initial_retry_delay * t, t >= 1
+     * Expon: retry_time(failure_time, t) = failure_time + initial_retry_delay ^ t, t >= 1
+     */
+    public interface BackoffPolicy {
+        public final int LINEAR = 0;
+        public final int EXPONENTIAL = 1;
+    }
+
+    /**
+     * Unique task id associated with this class. This is assigned to your task by the scheduler.
+     */
+    public int getTaskId() {
+        return taskId;
+    }
+
+    /**
+     * Bundle of extras which are returned to your application at execution time.
+     */
+    public Bundle getExtras() {
+        return extras;
+    }
+
+    /**
+     * Name of the service endpoint that will be called back into by the TaskManager.
+     */
+    public String getServiceClassName() {
+        return serviceClassName;
+    }
+
+    /**
+     * Whether this task needs the device to be plugged in.
+     */
+    public boolean isRequireCharging() {
+        return requireCharging;
+    }
+
+    /**
+     * Whether this task needs the device to be in an Idle maintenance window.
+     */
+    public boolean isRequireDeviceIdle() {
+        return requireDeviceIdle;
+    }
+
+    /**
+     * See {@link android.content.Task.NetworkType} for a description of this value.
+     */
+    public int getNetworkCapabilities() {
+        return networkCapabilities;
+    }
+
+    /**
+     * Set for a task that does not recur periodically, to specify a delay after which the task
+     * will be eligible for execution. This value is not set if the task recurs periodically.
+     */
+    public long getMinLatencyMillis() {
+        return minLatencyMillis;
+    }
+
+    /**
+     * See {@link Builder#setOverrideDeadline(long)}. This value is not set if the task recurs
+     * periodically.
+     */
+    public long getMaxExecutionDelayMillis() {
+        return maxExecutionDelayMillis;
+    }
+
+    /**
+     * Track whether this task will repeat with a given period.
+     */
+    public boolean isPeriodic() {
+        return isPeriodic;
+    }
+
+    /**
+     * Set to the interval between occurrences of this task. This value is <b>not</b> set if the
+     * task does not recur periodically.
+     */
+    public long getIntervalMillis() {
+        return intervalMillis;
+    }
+
+    /**
+     * The amount of time the TaskManager will wait before rescheduling a failed task. This value
+     * will be increased depending on the backoff policy specified at task creation time. Defaults
+     * to 5 seconds.
+     */
+    public long getInitialBackoffMillis() {
+        return initialBackoffMillis;
+    }
+
+    /**
+     * See {@link android.content.Task.BackoffPolicy} for an explanation of the values this field
+     * can take. This defaults to exponential.
+     */
+    public int getBackoffPolicy() {
+        return backoffPolicy;
+    }
+
+    private final int taskId;
+    // TODO: Change this to use PersistableBundle when that lands in master.
+    private final Bundle extras;
+    private final String serviceClassName;
+    private final boolean requireCharging;
+    private final boolean requireDeviceIdle;
+    private final int networkCapabilities;
+    private final long minLatencyMillis;
+    private final long maxExecutionDelayMillis;
+    private final boolean isPeriodic;
+    private final long intervalMillis;
+    private final long initialBackoffMillis;
+    private final int backoffPolicy;
+
+    private Task(Parcel in) {
+        taskId = in.readInt();
+        extras = in.readBundle();
+        serviceClassName = in.readString();
+        requireCharging = in.readInt() == 1;
+        requireDeviceIdle = in.readInt() == 1;
+        networkCapabilities = in.readInt();
+        minLatencyMillis = in.readLong();
+        maxExecutionDelayMillis = in.readLong();
+        isPeriodic = in.readInt() == 1;
+        intervalMillis = in.readLong();
+        initialBackoffMillis = in.readLong();
+        backoffPolicy = in.readInt();
+    }
+
+    private Task(Task.Builder b) {
+        taskId = b.mTaskId;
+        extras = new Bundle(b.mExtras);
+        serviceClassName = b.mTaskServiceClassName;
+        requireCharging = b.mRequiresCharging;
+        requireDeviceIdle = b.mRequiresDeviceIdle;
+        networkCapabilities = b.mNetworkCapabilities;
+        minLatencyMillis = b.mMinLatencyMillis;
+        maxExecutionDelayMillis = b.mMaxExecutionDelayMillis;
+        isPeriodic = b.mIsPeriodic;
+        intervalMillis = b.mIntervalMillis;
+        initialBackoffMillis = b.mInitialBackoffMillis;
+        backoffPolicy = b.mBackoffPolicy;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(taskId);
+        out.writeBundle(extras);
+        out.writeString(serviceClassName);
+        out.writeInt(requireCharging ? 1 : 0);
+        out.writeInt(requireDeviceIdle ? 1 : 0);
+        out.writeInt(networkCapabilities);
+        out.writeLong(minLatencyMillis);
+        out.writeLong(maxExecutionDelayMillis);
+        out.writeInt(isPeriodic ? 1 : 0);
+        out.writeLong(intervalMillis);
+        out.writeLong(initialBackoffMillis);
+        out.writeInt(backoffPolicy);
+    }
+
+    public static final Creator<Task> CREATOR = new Creator<Task>() {
+        @Override
+        public Task createFromParcel(Parcel in) {
+            return new Task(in);
+        }
+
+        @Override
+        public Task[] newArray(int size) {
+            return new Task[size];
+        }
+    };
+
+    /**
+     * Builder class for constructing {@link Task} objects.
+     */
+    public final class Builder {
+        private int mTaskId;
+        private Bundle mExtras;
+        private String mTaskServiceClassName;
+        // Requirements.
+        private boolean mRequiresCharging;
+        private boolean mRequiresDeviceIdle;
+        private int mNetworkCapabilities;
+        // One-off parameters.
+        private long mMinLatencyMillis;
+        private long mMaxExecutionDelayMillis;
+        // Periodic parameters.
+        private boolean mIsPeriodic;
+        private long mIntervalMillis;
+        // Back-off parameters.
+        private long mInitialBackoffMillis = 5000L;
+        private int mBackoffPolicy = BackoffPolicy.EXPONENTIAL;
+        /** Easy way to track whether the client has tried to set a back-off policy. */
+        private boolean mBackoffPolicySet = false;
+
+        /**
+         * @param taskId Application-provided id for this task. Subsequent calls to cancel, or
+         *               tasks created with the same taskId, will update the pre-existing task with
+         *               the same id.
+         * @param cls The endpoint that you implement that will receive the callback from the
+         *            TaskManager.
+         */
+        public Builder(int taskId, Class<TaskService> cls) {
+            mTaskServiceClassName = cls.getClass().getName();
+            mTaskId = taskId;
+        }
+
+        /**
+         * Set optional extras. This is persisted, so we only allow primitive types.
+         * @param extras Bundle containing extras you want the scheduler to hold on to for you.
+         */
+        public Builder setExtras(Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+         * Set some description of the kind of network capabilities you would like to have. This
+         * will be a parameter defined in {@link android.content.Task.NetworkType}.
+         * Not calling this function means the network is not necessary.
+         * Bear in mind that calling this function defines network as a strict requirement for your
+         * task if the network requested is not available your task will never run. See
+         * {@link #setOverrideDeadline(long)} to change this behaviour.
+         */
+        public Builder setRequiredNetworkCapabilities(int networkCapabilities) {
+            mNetworkCapabilities = networkCapabilities;
+            return this;
+        }
+
+        /*
+         * Specify that to run this task, the device needs to be plugged in. This defaults to
+         * false.
+         * @param requireCharging Whether or not the device is plugged in.
+         */
+        public Builder setRequiresCharging(boolean requiresCharging) {
+            mRequiresCharging = requiresCharging;
+            return this;
+        }
+
+        /**
+         * Specify that to run, the task needs the device to be in idle mode. This defaults to
+         * false.
+         * <p>Idle mode is a loose definition provided by the system, which means that the device
+         * is not in use, and has not been in use for some time. As such, it is a good time to
+         * perform resource heavy tasks. Bear in mind that battery usage will still be attributed
+         * to your application, and surfaced to the user in battery stats.</p>
+         * @param requiresDeviceIdle Whether or not the device need be within an idle maintenance
+         *                           window.
+         */
+        public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) {
+            mRequiresDeviceIdle = requiresDeviceIdle;
+            return this;
+        }
+
+        /**
+         * Specify that this task should recur with the provided interval, not more than once per
+         * period. You have no control over when within this interval this task will be executed,
+         * only the guarantee that it will be executed at most once within this interval.
+         * A periodic task will be repeated until the phone is turned off, however it will only be
+         * persisted if the client app has declared the
+         * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission. You can schedule
+         * periodic tasks without this permission, they simply will cease to exist after the phone
+         * restarts.
+         * Setting this function on the builder with {@link #setMinimumLatency(long)} or
+         * {@link #setOverrideDeadline(long)} will result in an error.
+         * @param intervalMillis Millisecond interval for which this task will repeat.
+         */
+        public Builder setPeriodic(long intervalMillis) {
+            mIsPeriodic = true;
+            mIntervalMillis = intervalMillis;
+            return this;
+        }
+
+        /**
+         * Specify that this task should be delayed by the provided amount of time.
+         * Because it doesn't make sense setting this property on a periodic task, doing so will
+         * throw an {@link java.lang.IllegalArgumentException} when
+         * {@link android.content.Task.Builder#build()} is called.
+         * @param minLatencyMillis Milliseconds before which this task will not be considered for
+         *                         execution.
+         */
+        public Builder setMinimumLatency(long minLatencyMillis) {
+            mMinLatencyMillis = minLatencyMillis;
+            return this;
+        }
+
+        /**
+         * Set deadline which is the maximum scheduling latency. The task will be run by this
+         * deadline even if other requirements are not met. Because it doesn't make sense setting
+         * this property on a periodic task, doing so will throw an
+         * {@link java.lang.IllegalArgumentException} when
+         * {@link android.content.Task.Builder#build()} is called.
+         */
+        public Builder setOverrideDeadline(long maxExecutionDelayMillis) {
+            mMaxExecutionDelayMillis = maxExecutionDelayMillis;
+            return this;
+        }
+
+        /**
+         * Set up the back-off/retry policy.
+         * This defaults to some respectable values: {5 seconds, Exponential}. We cap back-off at
+         * 1hr.
+         * Note that trying to set a backoff criteria for a task with
+         * {@link #setRequiresDeviceIdle(boolean)} will throw an exception when you call build().
+         * This is because back-off typically does not make sense for these types of tasks. See
+         * {@link android.app.task.TaskService#taskFinished(android.app.task.TaskParams, boolean)}
+         * for more description of the return value for the case of a task executing while in idle
+         * mode.
+         * @param initialBackoffMillis Millisecond time interval to wait initially when task has
+         *                             failed.
+         * @param backoffPolicy is one of {@link BackoffPolicy}
+         */
+        public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) {
+            mBackoffPolicySet = true;
+            mInitialBackoffMillis = initialBackoffMillis;
+            mBackoffPolicy = backoffPolicy;
+            return this;
+        }
+
+        /**
+         * @return The task object to hand to the TaskManager. This object is immutable.
+         */
+        public Task build() {
+            // Check that extras bundle only contains primitive types.
+            try {
+                for (String key : extras.keySet()) {
+                    Object value = extras.get(key);
+                    if (value == null) continue;
+                    if (value instanceof Long) continue;
+                    if (value instanceof Integer) continue;
+                    if (value instanceof Boolean) continue;
+                    if (value instanceof Float) continue;
+                    if (value instanceof Double) continue;
+                    if (value instanceof String) continue;
+                    throw new IllegalArgumentException("Unexpected value type: "
+                            + value.getClass().getName());
+                }
+            } catch (IllegalArgumentException e) {
+                throw e;
+            } catch (RuntimeException exc) {
+                throw new IllegalArgumentException("error unparcelling Bundle", exc);
+            }
+            // Check that a deadline was not set on a periodic task.
+            if (mIsPeriodic && (mMaxExecutionDelayMillis != 0L)) {
+                throw new IllegalArgumentException("Can't call setOverrideDeadline() on a " +
+                        "periodic task.");
+            }
+            if (mIsPeriodic && (mMinLatencyMillis != 0L)) {
+                throw new IllegalArgumentException("Can't call setMinimumLatency() on a " +
+                        "periodic task");
+            }
+            if (mBackoffPolicySet && mRequiresDeviceIdle) {
+                throw new IllegalArgumentException("An idle mode task will not respect any" +
+                        " back-off policy, so calling setBackoffCriteria with" +
+                        " setRequiresDeviceIdle is an error.");
+            }
+            return new Task(this);
+        }
+    }
+
+}
diff --git a/core/java/android/content/TaskManager.java b/core/java/android/content/TaskManager.java
new file mode 100644
index 0000000..d28d78a
--- /dev/null
+++ b/core/java/android/content/TaskManager.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.content;
+
+import java.util.List;
+
+/**
+ * Class for scheduling various types of tasks with the scheduling framework on the device.
+ *
+ * Get an instance of this class through {@link Context#getSystemService(String)}.
+ */
+public abstract class TaskManager {
+    /*
+     * Returned from {@link #schedule(Task)} when an invalid parameter was supplied. This can occur
+     * if the run-time for your task is too short, or perhaps the system can't resolve the
+     * requisite {@link TaskService} in your package.
+     */
+    static final int RESULT_INVALID_PARAMETERS = -1;
+    /**
+     * Returned from {@link #schedule(Task)} if this application has made too many requests for
+     * work over too short a time.
+     */
+    // TODO: Determine if this is necessary.
+    static final int RESULT_OVER_QUOTA = -2;
+
+    /*
+     * @param task The task you wish scheduled. See {@link Task#TaskBuilder} for more detail on
+     * the sorts of tasks you can schedule.
+     * @return If >0, this int corresponds to the taskId of the successfully scheduled task.
+     * Otherwise you have to compare the return value to the error codes defined in this class.
+     */
+    public abstract int schedule(Task task);
+
+    /**
+     * Cancel a task that is pending in the TaskManager.
+     * @param taskId unique identifier for this task. Obtain this value from the tasks returned by
+     * {@link #getAllPendingTasks()}.
+     * @return
+     */
+    public abstract void cancel(int taskId);
+
+    /**
+     * Cancel all tasks that have been registered with the TaskManager by this package.
+     */
+    public abstract void cancelAll();
+
+    /**
+     * @return a list of all the tasks registered by this package that have not yet been executed.
+     */
+    public abstract List<Task> getAllPendingTasks();
+
+}
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 796b113..0acf043 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -35,4 +35,6 @@
     ResolveInfo resolveActivity(in Intent intent, in UserHandle user);
     void startActivityAsUser(in ComponentName component, in Rect sourceBounds,
             in Bundle opts, in UserHandle user);
+    boolean isPackageEnabled(String packageName, in UserHandle user);
+    boolean isActivityEnabled(in ComponentName component, in UserHandle user);
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 488e25f..cf9a296 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -111,6 +111,8 @@
 
     ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
 
+    boolean canForwardTo(in Intent intent, String resolvedType, int userIdFrom, int userIdDest);
+
     List<ResolveInfo> queryIntentActivities(in Intent intent, 
             String resolvedType, int flags, int userId);
 
@@ -245,6 +247,10 @@
 
     void clearPackagePersistentPreferredActivities(String packageName, int userId);
 
+    void addForwardingIntentFilter(in IntentFilter filter, int userIdOrig, int userIdDest);
+
+    void clearForwardingIntentFilters(int userIdOrig);
+
     /**
      * Report the set of 'Home' activity candidates, plus (if any) which of them
      * is the current "always use this one" setting.
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 5187181..8025b60 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -187,6 +187,39 @@
     }
 
     /**
+     * Checks if the package is installed and enabled for a profile.
+     *
+     * @param packageName The package to check.
+     * @param user The UserHandle of the profile.
+     *
+     * @return true if the package exists and is enabled.
+     */
+    public boolean isPackageEnabledForProfile(String packageName, UserHandle user) {
+        try {
+            return mService.isPackageEnabled(packageName, user);
+        } catch (RemoteException re) {
+            return false;
+        }
+    }
+
+    /**
+     * Checks if the activity exists and it enabled for a profile.
+     *
+     * @param component The activity to check.
+     * @param user The UserHandle of the profile.
+     *
+     * @return true if the activity exists and is enabled.
+     */
+    public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) {
+        try {
+            return mService.isActivityEnabled(component, user);
+        } catch (RemoteException re) {
+            return false;
+        }
+    }
+
+
+    /**
      * Adds a listener for changes to packages in current and managed profiles.
      *
      * @param listener The listener to add.
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index f53aa4c..c0383a3 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -27,8 +27,8 @@
  */
 public class UserInfo implements Parcelable {
 
-    /** 6 bits for user type */
-    public static final int FLAG_MASK_USER_TYPE = 0x0000003F;
+    /** 8 bits for user type */
+    public static final int FLAG_MASK_USER_TYPE = 0x000000FF;
 
     /**
      * *************************** NOTE ***************************
@@ -70,6 +70,11 @@
      */
     public static final int FLAG_MANAGED_PROFILE = 0x00000020;
 
+    /**
+     * Indicates that this user is disabled.
+     */
+    public static final int FLAG_DISABLED = 0x00000040;
+
 
     public static final int NO_PROFILE_GROUP_ID = -1;
 
@@ -117,6 +122,10 @@
         return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE;
     }
 
+    public boolean isEnabled() {
+        return (flags & FLAG_DISABLED) != FLAG_DISABLED;
+    }
+
     /**
      * @return true if this user can be switched to.
      **/
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 4879c23..1331777 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -137,42 +137,45 @@
 
     /**
      * 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) {
+    public 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_Light_DarkActionBar);
+                com.android.internal.R.array.system_theme_sdks,
+                com.android.internal.R.array.system_theme_styles);
     }
 
-    /** @hide */
-    public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo,
-            int dark, int deviceDefault) {
+    /**
+     * Returns the most appropriate default theme for the specified target SDK version.
+     *
+     * @param curTheme The current theme, or 0 if not specified.
+     * @param targetSdkVersion The target SDK version.
+     * @param sdkArrayId Identifier for integer array resource containing
+     *        sorted minimum SDK versions. First entry must be 0.
+     * @param themeArrayId Identifier for array resource containing the
+     *        default themes that map to SDK versions.
+     * @return A theme resource identifier
+     * @hide
+     */
+    public int selectSystemTheme(
+            int curTheme, int targetSdkVersion, int sdkArrayId, int themeArrayId) {
         if (curTheme != 0) {
             return curTheme;
         }
-        if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
-            return orig;
+
+        final int[] targetSdks = getIntArray(sdkArrayId);
+        final TypedArray defaultThemes = obtainTypedArray(themeArrayId);
+        for (int i = targetSdks.length - 1; i > 0; i--) {
+            if (targetSdkVersion >= targetSdks[i]) {
+                return defaultThemes.getResourceId(i, 0);
+            }
         }
-        if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
-            return holo;
-        }
-        if (targetSdkVersion < Build.VERSION_CODES.CUR_DEVELOPMENT) {
-            return dark;
-        }
-        return deviceDefault;
+
+        return defaultThemes.getResourceId(0, 0);
     }
 
     /**
@@ -2308,8 +2311,8 @@
      */
     private Drawable loadDrawableForCookie(TypedValue value, int id, Theme theme) {
         if (value.string == null) {
-            throw new NotFoundException(
-                    "Resource is not a Drawable (color or path): " + value);
+            throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
+                    + Integer.toHexString(id) + ")  is not a Drawable (color or path): " + value);
         }
 
         final String file = value.string.toString();
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 722d956..28309d7 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -372,7 +372,6 @@
 
     /**
      * <p>Optional. Hyperfocal distance for this lens.</p>
-     * <p>If the lens is fixed focus, the camera device will report 0.</p>
      * <p>If the lens is not fixed focus, the camera device will report this
      * field when {@link CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION android.lens.info.focusDistanceCalibration} is APPROXIMATE or CALIBRATED.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index bb290af..9d0e0e1 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -192,8 +192,9 @@
      *
      * <p>The camera device will query each Surface's size and formats upon this
      * call, so they must be set to a valid setting at this time (in particular:
-     * if the format is user-visible, it must be one of android.scaler.availableFormats;
-     * and the size must be one of android.scaler.available[Processed|Jpeg]Sizes).</p>
+     * if the format is user-visible, it must be one of
+     * {@link StreamConfigurationMap#getOutputFormats}; and the size must be one of
+     * {@link StreamConfigurationMap#getOutputSizes(int)}).</p>
      *
      * <p>When this method is called with valid Surfaces, the device will transition to the {@link
      * StateListener#onBusy busy state}. Once configuration is complete, the device will transition
@@ -239,6 +240,9 @@
      * @see StateListener#onUnconfigured
      * @see #stopRepeating
      * @see #flush
+     * @see StreamConfigurationMap#getOutputFormats()
+     * @see StreamConfigurationMap#getOutputSizes(int)
+     * @see StreamConfigurationMap#getOutputSizes(Class)
      */
     public void configureOutputs(List<Surface> outputs) throws CameraAccessException;
 
diff --git a/core/java/android/hardware/camera2/ColorSpaceTransform.java b/core/java/android/hardware/camera2/ColorSpaceTransform.java
new file mode 100644
index 0000000..9912e4b
--- /dev/null
+++ b/core/java/android/hardware/camera2/ColorSpaceTransform.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class for describing a 3x3 matrix of {@link Rational} values in row-major order.
+ *
+ * <p>This matrix maps a transform from one color space to another. For the particular color space
+ * source and target, see the appropriate camera metadata documentation for the key that provides
+ * this value.</p>
+ *
+ * @see CameraMetadata
+ */
+public final class ColorSpaceTransform {
+
+    /** The number of rows in this matrix. */
+    private static final int ROWS = 3;
+
+    /** The number of columns in this matrix. */
+    private static final int COLUMNS = 3;
+
+    /** The number of total Rational elements in this matrix. */
+    private static final int COUNT = ROWS * COLUMNS;
+
+    /** Number of int elements in a rational. */
+    private static final int RATIONAL_SIZE = 2;
+
+    /** Numerator offset inside a rational (pair). */
+    private static final int OFFSET_NUMERATOR = 0;
+
+    /** Denominator offset inside a rational (pair). */
+    private static final int OFFSET_DENOMINATOR = 1;
+
+    /** Number of int elements in this matrix. */
+    private static final int COUNT_INT = ROWS * COLUMNS * RATIONAL_SIZE;
+
+    /**
+     * Create a new immutable {@link ColorSpaceTransform} instance from a {@link Rational} array.
+     *
+     * <p>The elements must be stored in a row-major order.</p>
+     *
+     * @param elements An array of {@code 9} elements
+     *
+     * @throws IllegalArgumentException
+     *            if the count of {@code elements} is not {@code 9}
+     * @throws NullPointerException
+     *            if {@code elements} or any sub-element is {@code null}
+     */
+    public ColorSpaceTransform(Rational[] elements) {
+
+        checkNotNull(elements, "elements must not be null");
+        if (elements.length != COUNT) {
+            throw new IllegalArgumentException("elements must be " + COUNT + " length");
+        }
+
+        mElements = new int[COUNT_INT];
+
+        for (int i = 0; i < elements.length; ++i) {
+            checkNotNull(elements, "element[" + i + "] must not be null");
+            mElements[i * RATIONAL_SIZE + OFFSET_NUMERATOR] = elements[i].getNumerator();
+            mElements[i * RATIONAL_SIZE + OFFSET_DENOMINATOR] = elements[i].getDenominator();
+        }
+    }
+
+    /**
+     * Create a new immutable {@link ColorSpaceTransform} instance from an {@code int} array.
+     *
+     * <p>The elements must be stored in a row-major order. Each rational is stored
+     * contiguously as a {@code (numerator, denominator)} pair.</p>
+     *
+     * <p>In particular:<pre>{@code
+     * int[] elements = new int[
+     *     N11, D11, N12, D12, N13, D13,
+     *     N21, D21, N22, D22, N23, D23,
+     *     N31, D31, N32, D32, N33, D33
+     * ];
+     *
+     * new ColorSpaceTransform(elements)}</pre>
+     *
+     * where {@code Nij} and {@code Dij} is the numerator and denominator for row {@code i} and
+     * column {@code j}.</p>
+     *
+     * @param elements An array of {@code 18} elements
+     *
+     * @throws IllegalArgumentException
+     *            if the count of {@code elements} is not {@code 18}
+     * @throws NullPointerException
+     *            if {@code elements} is {@code null}
+     */
+    public ColorSpaceTransform(int[] elements) {
+        checkNotNull(elements, "elements must not be null");
+        if (elements.length != COUNT_INT) {
+            throw new IllegalArgumentException("elements must be " + COUNT_INT + " length");
+        }
+
+        for (int i = 0; i < elements.length; ++i) {
+            checkNotNull(elements, "element " + i + " must not be null");
+        }
+
+        mElements = Arrays.copyOf(elements, elements.length);
+    }
+
+    /**
+     * Get an element of this matrix by its row and column.
+     *
+     * <p>The rows must be within the range [0, 3),
+     * and the column must be within the range [0, 3).</p>
+     *
+     * @return element (non-{@code null})
+     *
+     * @throws IllegalArgumentException if column or row was out of range
+     */
+    public Rational getElement(int column, int row) {
+        if (column < 0 || column >= COLUMNS) {
+            throw new IllegalArgumentException("column out of range");
+        } else if (row < 0 || row >= ROWS) {
+            throw new IllegalArgumentException("row out of range");
+        }
+
+        int numerator = mElements[row * ROWS * RATIONAL_SIZE + column + OFFSET_NUMERATOR];
+        int denominator = mElements[row * ROWS * RATIONAL_SIZE + column + OFFSET_DENOMINATOR];
+
+        return new Rational(numerator, denominator);
+    }
+
+    /**
+     * Copy the {@link Rational} elements in row-major order from this matrix into the destination.
+     *
+     * @param destination
+     *          an array big enough to hold at least {@code 9} elements after the
+     *          {@code offset}
+     * @param offset
+     *          a non-negative offset into the array
+     * @throws NullPointerException
+     *          If {@code destination} was {@code null}
+     * @throws ArrayIndexOutOfBoundsException
+     *          If there's not enough room to write the elements at the specified destination and
+     *          offset.
+     */
+    public void copyElements(Rational[] destination, int offset) {
+        checkArgumentNonnegative(offset, "offset must not be negative");
+        checkNotNull(destination, "destination must not be null");
+        if (destination.length + offset < COUNT) {
+            throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+        }
+
+        for (int i = 0, j = 0; i < COUNT; ++i, j += RATIONAL_SIZE) {
+            int numerator = mElements[j + OFFSET_NUMERATOR];
+            int denominator = mElements[j + OFFSET_DENOMINATOR];
+
+            destination[i + offset] = new Rational(numerator, denominator);
+        }
+    }
+
+    /**
+     * Copy the {@link Rational} elements in row-major order from this matrix into the destination.
+     *
+     * <p>Each element is stored as a contiguous rational packed as a
+     * {@code (numerator, denominator)} pair of ints, identical to the
+     * {@link ColorSpaceTransform#ColorSpaceTransform(int[]) constructor}.</p>
+     *
+     * @param destination
+     *          an array big enough to hold at least {@code 18} elements after the
+     *          {@code offset}
+     * @param offset
+     *          a non-negative offset into the array
+     * @throws NullPointerException
+     *          If {@code destination} was {@code null}
+     * @throws ArrayIndexOutOfBoundsException
+     *          If there's not enough room to write the elements at the specified destination and
+     *          offset.
+     *
+     * @see ColorSpaceTransform#ColorSpaceTransform(int[])
+     */
+    public void copyElements(int[] destination, int offset) {
+        checkArgumentNonnegative(offset, "offset must not be negative");
+        checkNotNull(destination, "destination must not be null");
+        if (destination.length + offset < COUNT_INT) {
+            throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+        }
+
+        // Manual copy faster than System#arraycopy for very small loops
+        for (int i = 0; i < COUNT_INT; ++i) {
+            destination[i + offset] = mElements[i];
+        }
+    }
+
+    /**
+     * Check if this {@link ColorSpaceTransform} is equal to another {@link ColorSpaceTransform}.
+     *
+     * <p>Two color space transforms are equal if and only if all of their elements are
+     * {@link Object#equals equal}.</p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ColorSpaceTransform) {
+            final ColorSpaceTransform other = (ColorSpaceTransform) obj;
+            return Arrays.equals(mElements, other.mElements);
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return HashCodeHelpers.hashCode(mElements);
+    }
+
+    private final int[] mElements;
+};
diff --git a/core/java/android/hardware/camera2/LensShadingMap.java b/core/java/android/hardware/camera2/LensShadingMap.java
new file mode 100644
index 0000000..2c224f64
--- /dev/null
+++ b/core/java/android/hardware/camera2/LensShadingMap.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import static android.hardware.camera2.RggbChannelVector.*;
+
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class for describing a {@code 4 x N x M} lens shading map of floats.
+ *
+ * @see CameraCharacteristics#LENS_SHADING_MAP
+ */
+public final class LensShadingMap {
+
+    /**
+     * The smallest gain factor in this map.
+     *
+     * <p>All values in this map will be at least this large.</p>
+     */
+    public static final float MINIMUM_GAIN_FACTOR = 1.0f;
+
+    /**
+     * Create a new immutable LensShadingMap instance.
+     *
+     * <p>The elements must be stored in a row-major order (fully packed).</p>
+     *
+     * <p>This constructor takes over the array; do not write to the array afterwards.</p>
+     *
+     * @param elements
+     *          An array of elements whose length is
+     *          {@code RggbChannelVector.COUNT * rows * columns}
+     *
+     * @throws IllegalArgumentException
+     *            if the {@code elements} array length is invalid,
+     *            if any of the subelems are not finite or less than {@value #MINIMUM_GAIN_FACTOR},
+     *            or if rows or columns is not positive
+     * @throws NullPointerException
+     *            if {@code elements} is {@code null}
+     *
+     * @hide
+     */
+    public LensShadingMap(final float[] elements, final int rows, final int columns) {
+
+        mRows = checkArgumentPositive(rows, "rows must be positive");
+        mColumns = checkArgumentPositive(rows, "columns must be positive");
+        mElements = checkNotNull(elements, "elements must not be null");
+
+        if (elements.length != getGainFactorCount()) {
+            throw new IllegalArgumentException("elements must be " + getGainFactorCount() +
+                    " length");
+        }
+
+        // Every element must be finite and >= 1.0f
+        checkArrayElementsInRange(elements, MINIMUM_GAIN_FACTOR, Float.MAX_VALUE, "elements");
+    }
+
+    /**
+     * Get the number of rows in this map.
+     */
+    public int getRowCount() {
+        return mRows;
+    }
+
+    /**
+     * Get the number of columns in this map.
+     */
+    public int getColumnCount() {
+        return mColumns;
+    }
+
+    /**
+     * Get the total number of gain factors in this map.
+     *
+     * <p>A single gain factor contains exactly one color channel.
+     * Use with {@link #copyGainFactors} to allocate a large-enough array.</p>
+     */
+    public int getGainFactorCount() {
+        return mRows * mColumns * COUNT;
+    }
+
+    /**
+     * Get a single color channel gain factor from this lens shading map by its row and column.
+     *
+     * <p>The rows must be within the range [0, {@link #getRowCount}),
+     * the column must be within the range [0, {@link #getColumnCount}),
+     * and the color channel must be within the range [0, {@value RggbChannelVector#COUNT}).</p>
+     *
+     * <p>The channel order is {@code [R, Geven, Godd, B]}, where
+     * {@code Geven} is the green channel for the even rows of a Bayer pattern, and
+     * {@code Godd} is the odd rows.
+     * </p>
+     *
+     * @param colorChannel color channel from {@code [R, Geven, Godd, B]}
+     * @param column within the range [0, {@link #getColumnCount})
+     * @param row within the range [0, {@link #getRowCount})
+     *
+     * @return a gain factor >= {@value #MINIMUM_GAIN_FACTOR}
+     *
+     * @throws IllegalArgumentException if any of the parameters was out of range
+     *
+     * @see #RED
+     * @see #GREEN_EVEN
+     * @see #GREEN_ODD
+     * @see #BLUE
+     * @see #getRowCount
+     * @see #getColumnCount
+     */
+    public float getGainFactor(final int colorChannel, final int column, final int row) {
+        if (colorChannel < 0 || colorChannel > COUNT) {
+            throw new IllegalArgumentException("colorChannel out of range");
+        } else if (column < 0 || column >= mColumns) {
+            throw new IllegalArgumentException("column out of range");
+        } else if (row < 0 || row >= mRows) {
+            throw new IllegalArgumentException("row out of range");
+        }
+
+        return mElements[colorChannel + (row * mColumns +  column) * COUNT ];
+    }
+
+    /**
+     * Get a gain factor vector from this lens shading map by its row and column.
+     *
+     * <p>The rows must be within the range [0, {@link #getRowCount}),
+     * the column must be within the range [0, {@link #getColumnCount}).</p>
+     *
+     * @param column within the range [0, {@link #getColumnCount})
+     * @param row within the range [0, {@link #getRowCount})
+     *
+     * @return an {@link RggbChannelVector} where each gain factor >= {@value #MINIMUM_GAIN_FACTOR}
+     *
+     * @throws IllegalArgumentException if any of the parameters was out of range
+     *
+     * @see #getRowCount
+     * @see #getColumnCount
+     */
+    public RggbChannelVector getGainFactorVector(final int column, final int row) {
+        if (column < 0 || column >= mColumns) {
+            throw new IllegalArgumentException("column out of range");
+        } else if (row < 0 || row >= mRows) {
+            throw new IllegalArgumentException("row out of range");
+        }
+
+        final int offset = (row * mColumns +  column) * COUNT;
+
+        final float red =
+                mElements[RED + offset];
+        final float greenEven =
+                mElements[GREEN_EVEN + offset];
+        final float greenOdd =
+                mElements[GREEN_ODD + offset];
+        final float blue =
+                mElements[BLUE + offset];
+
+        return new RggbChannelVector(red, greenEven, greenOdd, blue);
+    }
+
+    /**
+     * Copy all gain factors in row-major order from this lens shading map into the destination.
+     *
+     * <p>Each gain factor will be >= {@link #MINIMUM_GAIN_FACTOR}.</p>
+     *
+     * @param destination
+     *          an array big enough to hold at least {@link RggbChannelVector#COUNT}
+     *          elements after the {@code offset}
+     * @param offset
+     *          a non-negative offset into the array
+     * @throws NullPointerException
+     *          If {@code destination} was {@code null}
+     * @throws IllegalArgumentException
+     *          If offset was negative
+     * @throws ArrayIndexOutOfBoundsException
+     *          If there's not enough room to write the elements at the specified destination and
+     *          offset.
+     *
+     * @see CaptureResult#STATISTICS_LENS_SHADING_MAP
+     */
+    public void copyGainFactors(final float[] destination, final int offset) {
+        checkArgumentNonnegative(offset, "offset must not be negative");
+        checkNotNull(destination, "destination must not be null");
+        if (destination.length + offset < getGainFactorCount()) {
+            throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+        }
+
+        System.arraycopy(mElements, /*srcPos*/0, destination, offset, getGainFactorCount());
+    }
+
+    /**
+     * Check if this LensShadingMap is equal to another LensShadingMap.
+     *
+     * <p>Two lens shading maps are equal if and only if they have the same rows/columns,
+     * and all of their elements are {@link Object#equals equal}.</p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof LensShadingMap) {
+            final LensShadingMap other = (LensShadingMap) obj;
+            return mRows == other.mRows
+                    && mColumns == other.mColumns
+                    && Arrays.equals(mElements, other.mElements);
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        int elemsHash = HashCodeHelpers.hashCode(mElements);
+        return HashCodeHelpers.hashCode(mRows, mColumns, elemsHash);
+    }
+
+
+    private final int mRows;
+    private final int mColumns;
+    private final float[] mElements;
+};
diff --git a/core/java/android/hardware/camera2/MeteringRectangle.java b/core/java/android/hardware/camera2/MeteringRectangle.java
new file mode 100644
index 0000000..ff7a745
--- /dev/null
+++ b/core/java/android/hardware/camera2/MeteringRectangle.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2;
+
+import android.util.Size;
+import static com.android.internal.util.Preconditions.*;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+/**
+ * An immutable class to represent a rectangle {@code (x,y, width, height)} with an
+ * additional weight component.
+ *
+ * </p>The rectangle is defined to be inclusive of the specified coordinates.</p>
+ *
+ * <p>When used with a {@link CaptureRequest}, the coordinate system is based on the active pixel
+ * array, with {@code (0,0)} being the top-left pixel in the
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE active pixel array}, and
+ * {@code (android.sensor.info.activeArraySize.width - 1,
+ * android.sensor.info.activeArraySize.height - 1)}
+ * being the bottom-right pixel in the active pixel array.
+ * </p>
+ *
+ * <p>The metering weight is nonnegative.</p>
+ */
+public final class MeteringRectangle {
+
+    private final int mX;
+    private final int mY;
+    private final int mWidth;
+    private final int mHeight;
+    private final int mWeight;
+
+    /**
+     * Create a new metering rectangle.
+     *
+     * @param x coordinate >= 0
+     * @param y coordinate >= 0
+     * @param width width >= 0
+     * @param height height >= 0
+     * @param meteringWeight weight >= 0
+     *
+     * @throws IllegalArgumentException if any of the parameters were non-negative
+     */
+    public MeteringRectangle(int x, int y, int width, int height, int meteringWeight) {
+        mX = checkArgumentNonnegative(x, "x must be nonnegative");
+        mY = checkArgumentNonnegative(y, "y must be nonnegative");
+        mWidth = checkArgumentNonnegative(width, "width must be nonnegative");
+        mHeight = checkArgumentNonnegative(height, "height must be nonnegative");
+        mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
+    }
+
+    /**
+     * Create a new metering rectangle.
+     *
+     * @param xy a non-{@code null} {@link Point} with both x,y >= 0
+     * @param dimensions a non-{@code null} {@link android.util.Size Size} with width, height >= 0
+     * @param meteringWeight weight >= 0
+     *
+     * @throws IllegalArgumentException if any of the parameters were non-negative
+     * @throws NullPointerException if any of the arguments were null
+     */
+    public MeteringRectangle(Point xy, Size dimensions, int meteringWeight) {
+        checkNotNull(xy, "xy must not be null");
+        checkNotNull(dimensions, "dimensions must not be null");
+
+        mX = checkArgumentNonnegative(xy.x, "x must be nonnegative");
+        mY = checkArgumentNonnegative(xy.y, "y must be nonnegative");
+        mWidth = checkArgumentNonnegative(dimensions.getWidth(), "width must be nonnegative");
+        mHeight = checkArgumentNonnegative(dimensions.getHeight(), "height must be nonnegative");
+        mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
+    }
+
+    /**
+     * Create a new metering rectangle.
+     *
+     * @param rect a non-{@code null} rectangle with all x,y,w,h dimensions >= 0
+     * @param meteringWeight weight >= 0
+     *
+     * @throws IllegalArgumentException if any of the parameters were non-negative
+     * @throws NullPointerException if any of the arguments were null
+     */
+    public MeteringRectangle(Rect rect, int meteringWeight) {
+        checkNotNull(rect, "rect must not be null");
+
+        mX = checkArgumentNonnegative(rect.left, "rect.left must be nonnegative");
+        mY = checkArgumentNonnegative(rect.top, "rect.top must be nonnegative");
+        mWidth = checkArgumentNonnegative(rect.width(), "rect.width must be nonnegative");
+        mHeight = checkArgumentNonnegative(rect.height(), "rect.height must be nonnegative");
+        mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
+    }
+
+    /**
+     * Return the X coordinate of the left side of the rectangle.
+     *
+     * @return x coordinate >= 0
+     */
+    public int getX() {
+        return mX;
+    }
+
+    /**
+     * Return the Y coordinate of the upper side of the rectangle.
+     *
+     * @return y coordinate >= 0
+     */
+    public int getY() {
+        return mY;
+    }
+
+    /**
+     * Return the width of the rectangle.
+     *
+     * @return width >= 0
+     */
+    public int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * Return the height of the rectangle.
+     *
+     * @return height >= 0
+     */
+    public int getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * Return the metering weight of the rectangle.
+     *
+     * @return weight >= 0
+     */
+    public int getMeteringWeight() {
+        return mWeight;
+    }
+
+    /**
+     * Convenience method to create the upper-left (X,Y) coordinate as a {@link Point}.
+     *
+     * @return {@code (x,y)} point with both x,y >= 0
+     */
+    public Point getUpperLeftPoint() {
+        return new Point(mX, mY);
+    }
+
+    /**
+     * Convenience method to create the size from this metering rectangle.
+     *
+     * <p>This strips away the X,Y,weight from the rectangle.</p>
+     *
+     * @return a Size with non-negative width and height
+     */
+    public Size getSize() {
+        return new Size(mWidth, mHeight);
+    }
+
+    /**
+     * Convenience method to create a {@link Rect} from this metering rectangle.
+     *
+     * <p>This strips away the weight from the rectangle.</p>
+     *
+     * @return a {@link Rect} with non-negative x1, y1, x2, y2
+     */
+    public Rect getRect() {
+        return new Rect(mX, mY, mX + mWidth, mY + mHeight);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(final Object other) {
+        if (other instanceof MeteringRectangle) {
+            return equals(other);
+        }
+        return false;
+    }
+
+    /**
+     * Compare two metering rectangles to see if they are equal.
+     *
+     * Two weighted rectangles are only considered equal if each of their components
+     * (x, y, width, height, weight) is respectively equal.
+     *
+     * @param other Another MeteringRectangle
+     *
+     * @return {@code true} if the metering rectangles are equal, {@code false} otherwise
+     */
+    public boolean equals(final MeteringRectangle other) {
+        if (other == null) {
+            return false;
+        }
+
+        return (mX == other.mX
+                && mY == other.mY
+                && mWidth == other.mWidth
+                && mHeight == other.mHeight
+                && mWidth == other.mWidth);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return HashCodeHelpers.hashCode(mX, mY, mWidth, mHeight, mWeight);
+    }
+}
diff --git a/core/java/android/hardware/camera2/ReprocessFormatsMap.java b/core/java/android/hardware/camera2/ReprocessFormatsMap.java
new file mode 100644
index 0000000..c6c59d4
--- /dev/null
+++ b/core/java/android/hardware/camera2/ReprocessFormatsMap.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class to store the input to output formats
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP map} to be used for with
+ * camera image reprocessing.
+ *
+ * <p>
+ * The mapping of image formats that are supported by this camera device for input streams,
+ * to their corresponding output formats.</p>
+ *
+ * <p>
+ * Attempting to configure an input stream with output streams not listed as available in this map
+ * is not valid.
+ * </p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ *
+ * <!-- hide this until we expose input streams through public API -->
+ * @hide
+ */
+public final class ReprocessFormatsMap {
+    /**
+     * Create a new {@link ReprocessFormatsMap}
+     *
+     * <p>This value is encoded as a variable-size array-of-arrays.
+     * The inner array always contains {@code [format, length, ...]} where ... has length elements.
+     * An inner array is followed by another inner array if the total metadata entry size hasn't
+     * yet been exceeded.</p>
+     *
+     * <p>Entry must not be {@code null}. Empty array is acceptable.</p>
+     *
+     * <p>The entry array ownership is passed to this instance after construction; do not
+     * write to it afterwards.</p>
+     *
+     * @param entry Array of ints, not yet deserialized (not-null)
+     *
+     * @throws IllegalArgumentException
+     *              if the data was poorly formatted
+     *              (missing output format length or too few output formats)
+     * @throws NullPointerException
+     *              if entry was null
+     *
+     * @hide
+     */
+    public ReprocessFormatsMap(final int[] entry) {
+        checkNotNull(entry, "entry must not be null");
+
+        int numInputs = 0;
+        int left = entry.length;
+        for (int i = 0; i < entry.length; ) {
+            final int format = entry[i];
+
+            left--;
+            i++;
+
+            if (left < 1) {
+                throw new IllegalArgumentException(
+                        String.format("Input %x had no output format length listed", format));
+            }
+
+            final int length = entry[i];
+            left--;
+            i++;
+
+            if (length > 0) {
+                if (left < length) {
+                    throw new IllegalArgumentException(
+                            String.format(
+                                    "Input %x had too few output formats listed (actual: %d, " +
+                                    "expected: %d)", format, left, length));
+                }
+
+                i += length;
+                left -= length;
+            }
+
+            numInputs++;
+        }
+
+        mEntry = entry;
+        mInputCount = numInputs;
+    }
+
+    /**
+     * Get a list of all input image formats that can be used to reprocess an input
+     * stream into an output stream.
+     *
+     * <p>Use this input format to look up the available output formats with {@link #getOutputs}.
+     * </p>
+     *
+     * @return an array of inputs (possibly empty, but never {@code null})
+     *
+     * @see ImageFormat
+     * @see #getOutputs
+     */
+    public int[] getInputs() {
+        final int[] inputs = new int[mInputCount];
+
+        int left = mEntry.length;
+        for (int i = 0, j = 0; i < mEntry.length; j++) {
+            final int format = mEntry[i];
+
+            left--;
+            i++;
+
+            if (left < 1) {
+                throw new AssertionError(
+                        String.format("Input %x had no output format length listed", format));
+            }
+            // TODO: check format is a valid input format
+
+            final int length = mEntry[i];
+            left--;
+            i++;
+
+            if (length > 0) {
+                if (left < length) {
+                    throw new AssertionError(
+                            String.format(
+                                    "Input %x had too few output formats listed (actual: %d, " +
+                                    "expected: %d)", format, left, length));
+                }
+
+                i += length;
+                left -= length;
+            }
+
+            // TODO: check output format is a valid output format
+
+            inputs[j] = format;
+        }
+
+        return inputs;
+    }
+
+    /**
+     * Get the list of output formats that can be reprocessed into from the input {@code format}.
+     *
+     * <p>The input {@code format} must be one of the formats returned by {@link #getInputs}.</p>
+     *
+     * @param format an input format
+     *
+     * @return list of output image formats
+     *
+     * @see ImageFormat
+     * @see #getInputs
+     */
+    public int[] getOutputs(final int format) {
+
+        int left = mEntry.length;
+        for (int i = 0; i < mEntry.length; ) {
+            final int inputFormat = mEntry[i];
+
+            left--;
+            i++;
+
+            if (left < 1) {
+                throw new AssertionError(
+                        String.format("Input %x had no output format length listed", format));
+            }
+
+            final int length = mEntry[i];
+            left--;
+            i++;
+
+            if (length > 0) {
+                if (left < length) {
+                    throw new AssertionError(
+                            String.format(
+                                    "Input %x had too few output formats listed (actual: %d, " +
+                                    "expected: %d)", format, left, length));
+                }
+            }
+
+            if (inputFormat == format) {
+                int[] outputs = new int[length];
+
+                // Copying manually faster than System.arraycopy for small arrays
+                for (int k = 0; k < length; ++k) {
+                    outputs[k] = mEntry[i + k];
+                }
+
+                return outputs;
+            }
+
+            i += length;
+            left -= length;
+
+        }
+
+        throw new IllegalArgumentException(
+                String.format("Input format %x was not one in #getInputs", format));
+    }
+
+    /**
+     * Check if this {@link ReprocessFormatsMap} is equal to another
+     * {@link ReprocessFormatsMap}.
+     *
+     * <p>These two objects are only equal if and only if each of the respective elements is equal.
+     * </p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ReprocessFormatsMap) {
+            final ReprocessFormatsMap other = (ReprocessFormatsMap) obj;
+            // Do not compare anything besides mEntry, since the rest of the values are derived
+            return Arrays.equals(mEntry, other.mEntry);
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        // Do not hash anything besides mEntry since the rest of the values are derived
+        return HashCodeHelpers.hashCode(mEntry);
+    }
+
+    private final int[] mEntry;
+    /*
+     * Dependent fields: values are derived from mEntry
+     */
+    private final int mInputCount;
+}
diff --git a/core/java/android/hardware/camera2/RggbChannelVector.java b/core/java/android/hardware/camera2/RggbChannelVector.java
new file mode 100644
index 0000000..80167c6
--- /dev/null
+++ b/core/java/android/hardware/camera2/RggbChannelVector.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Immutable class to store a 4-element vector of floats indexable by a bayer RAW 2x2 pixel block.
+ */
+public final class RggbChannelVector {
+    /**
+     * The number of color channels in this vector.
+     */
+    public static final int COUNT = 4;
+
+    /** Red color channel in a bayer Raw pattern. */
+    public static final int RED = 0;
+
+    /** Green color channel in a bayer Raw pattern used by the even rows. */
+    public static final int GREEN_EVEN = 1;
+
+    /** Green color channel in a bayer Raw pattern used by the odd rows. */
+    public static final int GREEN_ODD = 2;
+
+    /** Blue color channel in a bayer Raw pattern. */
+    public static final int BLUE = 3;
+
+    /**
+     * Create a new {@link RggbChannelVector} from an RGGB 2x2 pixel.
+     *
+     * <p>All pixel values are considered normalized within {@code [0.0f, 1.0f]}
+     * (i.e. {@code 1.0f} could be linearized to {@code 255} if converting to a
+     * non-floating point pixel representation).</p>
+     *
+     * <p>All arguments must be finite; NaN and infinity is not allowed.</p>
+     *
+     * @param red red pixel
+     * @param greenEven green pixel (even row)
+     * @param greenOdd green pixel (odd row)
+     * @param blue blue pixel
+     *
+     * @throws IllegalArgumentException if any of the arguments were not finite
+     */
+    public RggbChannelVector(final float red, final float greenEven, final float greenOdd,
+            final float blue) {
+        mRed = checkArgumentFinite(red, "red");
+        mGreenEven = checkArgumentFinite(greenEven, "greenEven");
+        mGreenOdd = checkArgumentFinite(greenOdd, "greenOdd");
+        mBlue = checkArgumentFinite(blue, "blue");
+    }
+
+    /**
+     * Get the red component.
+     *
+     * @return a floating point value (guaranteed to be finite)
+     */
+    public final float getRed() {
+        return mRed;
+    }
+
+    /**
+     * Get the green (even rows) component.
+     *
+     * @return a floating point value (guaranteed to be finite)
+     */
+    public float getGreenEven() {
+        return mGreenEven;
+    }
+
+    /**
+     * Get the green (odd rows) component.
+     *
+     * @return a floating point value (guaranteed to be finite)
+     */
+    public float getGreenOdd() {
+        return mGreenOdd;
+    }
+
+    /**
+     * Get the blue component.
+     *
+     * @return a floating point value (guaranteed to be finite)
+     */
+    public float getBlue() {
+        return mBlue;
+    }
+
+    /**
+     * Get the component by the color channel index.
+     *
+     * <p>{@code colorChannel} must be one of {@link #RED}, {@link #GREEN_EVEN}, {@link #GREEN_ODD},
+     * {@link #BLUE}.</p>
+     *
+     * @param colorChannel greater or equal to {@code 0} and less than {@link #COUNT}
+     * @return a floating point value (guaranteed to be finite)
+     *
+     * @throws IllegalArgumentException if {@code colorChannel} was out of range
+     */
+    public float getComponent(final int colorChannel) {
+        if (colorChannel < 0 || colorChannel >= COUNT) {
+            throw new IllegalArgumentException("Color channel out of range");
+        }
+
+        switch (colorChannel) {
+            case RED:
+                return mRed;
+            case GREEN_EVEN:
+                return mGreenEven;
+            case GREEN_ODD:
+                return mGreenOdd;
+            case BLUE:
+                return mBlue;
+            default:
+                throw new AssertionError("Unhandled case " + colorChannel);
+        }
+    }
+
+    /**
+     * Copy the vector into the destination in the order {@code [R, Geven, Godd, B]}.
+     *
+     * @param destination
+     *          an array big enough to hold at least {@value #COUNT} elements after the
+     *          {@code offset}
+     * @param offset
+     *          a non-negative offset into the array
+     *
+     * @throws NullPointerException
+     *          If {@code destination} was {@code null}
+     * @throws ArrayIndexOutOfBoundsException
+     *          If there's not enough room to write the elements at the specified destination and
+     *          offset.
+     */
+    public void copyTo(final float[] destination, final int offset) {
+        checkNotNull(destination, "destination must not be null");
+        if (destination.length + offset < COUNT) {
+            throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+        }
+
+        destination[offset + RED] = mRed;
+        destination[offset + GREEN_EVEN] = mGreenEven;
+        destination[offset + GREEN_ODD] = mGreenOdd;
+        destination[offset + BLUE] = mBlue;
+    }
+
+    /**
+     * Check if this {@link RggbChannelVector} is equal to another {@link RggbChannelVector}.
+     *
+     * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof RggbChannelVector) {
+            final RggbChannelVector other = (RggbChannelVector) obj;
+            return mRed == other.mRed &&
+                    mGreenEven == other.mGreenEven &&
+                    mGreenOdd == other.mGreenOdd &&
+                    mBlue == other.mBlue;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return Float.floatToIntBits(mRed) ^
+                Float.floatToIntBits(mGreenEven) ^
+                Float.floatToIntBits(mGreenOdd) ^
+                Float.floatToIntBits(mBlue);
+    }
+
+    private final float mRed;
+    private final float mGreenEven;
+    private final float mGreenOdd;
+    private final float mBlue;
+}
diff --git a/core/java/android/hardware/camera2/Size.java b/core/java/android/hardware/camera2/Size.java
index 45aaeae..9328a003 100644
--- a/core/java/android/hardware/camera2/Size.java
+++ b/core/java/android/hardware/camera2/Size.java
@@ -16,32 +16,55 @@
 
 package android.hardware.camera2;
 
+// TODO: Delete this class, since it was moved to android.util as public API
+
 /**
- * A simple immutable class for describing the dimensions of camera image
- * buffers.
+ * Immutable class for describing width and height dimensions in pixels.
+ *
+ * @hide
  */
 public final class Size {
     /**
-     * Create a new immutable Size instance
+     * Create a new immutable Size instance.
      *
-     * @param width The width to store in the Size instance
-     * @param height The height to store in the Size instance
+     * @param width The width of the size, in pixels
+     * @param height The height of the size, in pixels
      */
-    public Size(int width, int height) {
+    public Size(final int width, final int height) {
         mWidth = width;
         mHeight = height;
     }
 
+    /**
+     * Get the width of the size (in pixels).
+     * @return width
+     */
     public final int getWidth() {
         return mWidth;
     }
 
+    /**
+     * Get the height of the size (in pixels).
+     * @return height
+     */
     public final int getHeight() {
         return mHeight;
     }
 
+    /**
+     * Check if this size is equal to another size.
+     * <p>
+     * Two sizes are equal if and only if both their widths and heights are
+     * equal.
+     * </p>
+     * <p>
+     * A size object is never equal to any other type of object.
+     * </p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (obj == null) {
             return false;
         }
@@ -49,27 +72,29 @@
             return true;
         }
         if (obj instanceof Size) {
-            Size other = (Size) obj;
+            final Size other = (Size) obj;
             return mWidth == other.mWidth && mHeight == other.mHeight;
         }
         return false;
     }
 
+    /**
+     * Return the size represented as a string with the format {@code "WxH"}
+     *
+     * @return string representation of the size
+     */
     @Override
     public String toString() {
         return mWidth + "x" + mHeight;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public int hashCode() {
-        final long INT_MASK = 0xffffffffL;
-
-        long asLong = INT_MASK & mWidth;
-        asLong <<= 32;
-
-        asLong |= (INT_MASK & mHeight);
-
-        return ((Long)asLong).hashCode();
+        // assuming most sizes are <2^16, doing a rotate will give us perfect hashing
+        return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
     }
 
     private final int mWidth;
diff --git a/core/java/android/hardware/camera2/StreamConfiguration.java b/core/java/android/hardware/camera2/StreamConfiguration.java
new file mode 100644
index 0000000..c53dd7c
--- /dev/null
+++ b/core/java/android/hardware/camera2/StreamConfiguration.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import static android.hardware.camera2.StreamConfigurationMap.checkArgumentFormatInternal;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.impl.HashCodeHelpers;
+import android.util.Size;
+
+/**
+ * Immutable class to store the available stream
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to be used
+ * when configuring streams with {@link CameraDevice#configureOutputs}.
+ * <!-- TODO: link to input stream configuration -->
+ *
+ * <p>This is the authoritative list for all input/output formats (and sizes respectively
+ * for that format) that are supported by a camera device.</p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ *
+ * @hide
+ */
+public final class StreamConfiguration {
+
+    /**
+     * Create a new {@link StreamConfiguration}.
+     *
+     * @param format image format
+     * @param width image width, in pixels (positive)
+     * @param height image height, in pixels (positive)
+     * @param input true if this is an input configuration, false for output configurations
+     *
+     * @throws IllegalArgumentException
+     *              if width/height were not positive
+     *              or if the format was not user-defined in ImageFormat/PixelFormat
+     *                  (IMPL_DEFINED is ok)
+     *
+     * @hide
+     */
+    public StreamConfiguration(
+            final int format, final int width, final int height, final boolean input) {
+        mFormat = checkArgumentFormatInternal(format);
+        mWidth = checkArgumentPositive(width, "width must be positive");
+        mHeight = checkArgumentPositive(width, "height must be positive");
+        mInput = input;
+    }
+
+    /**
+     * Get the image {@code format} in this stream configuration.
+     *
+     * @return an integer format
+     *
+     * @see ImageFormat
+     */
+    public final int getFormat() {
+        return mFormat;
+    }
+
+
+    /**
+     * Return the width of the stream configuration.
+     *
+     * @return width > 0
+     */
+    public int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * Return the height of the stream configuration.
+     *
+     * @return height > 0
+     */
+    public int getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * Convenience method to return the size of this stream configuration.
+     *
+     * @return a Size with positive width and height
+     */
+    public Size getSize() {
+        return new Size(mWidth, mHeight);
+    }
+
+    /**
+     * Determines if this configuration is usable for input streams.
+     *
+     * <p>Input and output stream configurations are not interchangeable;
+     * input stream configurations must be used when configuring inputs.</p>
+     *
+     * @return {@code true} if input configuration, {@code false} otherwise
+     */
+    public boolean isInput() {
+        return mInput;
+    }
+
+    /**
+     * Determines if this configuration is usable for output streams.
+     *
+     * <p>Input and output stream configurations are not interchangeable;
+     * out stream configurations must be used when configuring outputs.</p>
+     *
+     * @return {@code true} if output configuration, {@code false} otherwise
+     *
+     * @see CameraDevice#configureOutputs
+     */
+    public boolean isOutput() {
+        return !mInput;
+    }
+
+    /**
+     * Check if this {@link StreamConfiguration} is equal to another {@link StreamConfiguration}.
+     *
+     * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof StreamConfiguration) {
+            final StreamConfiguration other = (StreamConfiguration) obj;
+            return mFormat == other.mFormat &&
+                    mWidth == other.mWidth &&
+                    mHeight == other.mHeight &&
+                    mInput == other.mInput;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight, mInput ? 1 : 0);
+    }
+
+    private final int mFormat;
+    private final int mWidth;
+    private final int mHeight;
+    private final boolean mInput;
+}
diff --git a/core/java/android/hardware/camera2/StreamConfigurationDuration.java b/core/java/android/hardware/camera2/StreamConfigurationDuration.java
new file mode 100644
index 0000000..189ae62
--- /dev/null
+++ b/core/java/android/hardware/camera2/StreamConfigurationDuration.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import static android.hardware.camera2.StreamConfigurationMap.checkArgumentFormatInternal;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.impl.HashCodeHelpers;
+import android.util.Size;
+
+/**
+ * Immutable class to store a time duration for any given format/size combination.
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS
+ *
+ * @hide
+ */
+public final class StreamConfigurationDuration {
+
+    /**
+     * Create a new {@link StreamConfigurationDuration}.
+     *
+     * @param format image format
+     * @param width image width, in pixels (positive)
+     * @param height image height, in pixels (positive)
+     * @param durationNs duration in nanoseconds (non-negative)
+     *
+     * @throws IllegalArgumentException
+     *          if width/height were not positive, or durationNs was negative
+     *          or if the format was not user-defined in ImageFormat/PixelFormat
+     *              (IMPL_DEFINED is OK)
+     *
+     *
+     * @hide
+     */
+    public StreamConfigurationDuration(
+            final int format, final int width, final int height, final long durationNs) {
+        mFormat =  checkArgumentFormatInternal(format);
+        mWidth = checkArgumentPositive(width, "width must be positive");
+        mHeight = checkArgumentPositive(width, "height must be positive");
+        mDurationNs = checkArgumentNonnegative(durationNs, "durationNs must be non-negative");
+    }
+
+    /**
+     * Get the image {@code format} in this stream configuration duration
+     *
+     * @return an integer format
+     *
+     * @see ImageFormat
+     */
+    public final int getFormat() {
+        return mFormat;
+    }
+
+
+    /**
+     * Return the width of the stream configuration duration.
+     *
+     * @return width > 0
+     */
+    public int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * Return the height of the stream configuration duration
+     *
+     * @return height > 0
+     */
+    public int getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * Convenience method to return the size of this stream configuration duration.
+     *
+     * @return a Size with positive width and height
+     */
+    public Size getSize() {
+        return new Size(mWidth, mHeight);
+    }
+
+    /**
+     * Get the time duration (in nanoseconds).
+     *
+     * @return long >= 0
+     */
+    public long getDuration() {
+        return mDurationNs;
+    }
+
+    /**
+     * Check if this {@link StreamConfigurationDuration} is equal to another
+     * {@link StreamConfigurationDuration}.
+     *
+     * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof StreamConfigurationDuration) {
+            final StreamConfigurationDuration other = (StreamConfigurationDuration) obj;
+            return mFormat == other.mFormat &&
+                    mWidth == other.mWidth &&
+                    mHeight == other.mHeight &&
+                    mDurationNs == other.mDurationNs;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight,
+                (int) mDurationNs, (int)(mDurationNs >>> Integer.SIZE));
+    }
+
+    private final int mFormat;
+    private final int mWidth;
+    private final int mHeight;
+    private final long mDurationNs;
+}
diff --git a/core/java/android/hardware/camera2/StreamConfigurationMap.java b/core/java/android/hardware/camera2/StreamConfigurationMap.java
new file mode 100644
index 0000000..e24fd1b
--- /dev/null
+++ b/core/java/android/hardware/camera2/StreamConfigurationMap.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
+import android.hardware.camera2.impl.HashCodeHelpers;
+import android.view.Surface;
+import android.util.Size;
+
+import java.util.Arrays;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Immutable class to store the available stream
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to be used
+ * when configuring streams with {@link CameraDevice#configureOutputs}.
+ * <!-- TODO: link to input stream configuration -->
+ *
+ * <p>This is the authoritative list for all <!-- input/ -->output formats (and sizes respectively
+ * for that format) that are supported by a camera device.</p>
+ *
+ * <p>This also contains the minimum frame durations and stall durations for each format/size
+ * combination that can be used to calculate effective frame rate when submitting multiple captures.
+ * </p>
+ *
+ * <p>An instance of this object is available from {@link CameraCharacteristics} using
+ * the {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS} key and the
+ * {@link CameraCharacteristics#get} method.</p.
+ *
+ * <pre>{@code
+ * CameraCharacteristics characteristics = ...;
+ * StreamConfigurationMap configs = characteristics.get(
+ *         CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ * }</pre>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ * @see CameraDevice#configureOutputs
+ */
+public final class StreamConfigurationMap {
+
+    /**
+     * Create a new {@link StreamConfigurationMap}.
+     *
+     * <p>The array parameters ownership is passed to this object after creation; do not
+     * write to them after this constructor is invoked.</p>
+     *
+     * @param configurations a non-{@code null} array of {@link StreamConfiguration}
+     * @param durations a non-{@code null} array of {@link StreamConfigurationDuration}
+     *
+     * @throws NullPointerException if any of the arguments or subelements were {@code null}
+     *
+     * @hide
+     */
+    public StreamConfigurationMap(
+            StreamConfiguration[] configurations,
+            StreamConfigurationDuration[] durations) {
+        // TODO: format check against ImageFormat/PixelFormat ?
+
+        mConfigurations = checkArrayElementsNotNull(configurations, "configurations");
+        mDurations = checkArrayElementsNotNull(durations, "durations");
+
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Get the image {@code format} output formats in this stream configuration.
+     *
+     * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
+     * or in {@link PixelFormat} (and there is no possibility of collision).</p>
+     *
+     * <p>Formats listed in this array are guaranteed to return true if queried with
+     * {@link #isOutputSupportedFor(int).</p>
+     *
+     * @return an array of integer format
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public final int[] getOutputFormats() {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Get the image {@code format} input formats in this stream configuration.
+     *
+     * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
+     * or in {@link PixelFormat} (and there is no possibility of collision).</p>
+     *
+     * @return an array of integer format
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     *
+     * @hide
+     */
+    public final int[] getInputFormats() {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Get the supported input sizes for this input format.
+     *
+     * <p>The format must have come from {@link #getInputFormats}; otherwise
+     * {@code null} is returned.</p>
+     *
+     * @param format a format from {@link #getInputFormats}
+     * @return a non-empty array of sizes, or {@code null} if the format was not available.
+     *
+     * @hide
+     */
+    public Size[] getInputSizes(final int format) {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Determine whether or not output streams can be
+     * {@link CameraDevice#configureOutputs configured} with a particular user-defined format.
+     *
+     * <p>This method determines that the output {@code format} is supported by the camera device;
+     * each output {@code surface} target may or may not itself support that {@code format}.
+     * Refer to the class which provides the surface for additional documentation.</p>
+     *
+     * <p>Formats for which this returns {@code true} are guaranteed to exist in the result
+     * returned by {@link #getOutputSizes}.</p>
+     *
+     * @param format an image format from either {@link ImageFormat} or {@link PixelFormat}
+     * @return
+     *          {@code true} iff using a {@code surface} with this {@code format} will be
+     *          supported with {@link CameraDevice#configureOutputs}
+     *
+     * @throws IllegalArgumentException
+     *          if the image format was not a defined named constant
+     *          from either {@link ImageFormat} or {@link PixelFormat}
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     * @see CameraDevice#configureOutputs
+     */
+    public boolean isOutputSupportedFor(int format) {
+        checkArgumentFormat(format);
+
+        final int[] formats = getOutputFormats();
+        for (int i = 0; i < formats.length; ++i) {
+            if (format == formats[i]) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Determine whether or not output streams can be configured with a particular class
+     * as a consumer.
+     *
+     * <p>The following list is generally usable for outputs:
+     * <ul>
+     * <li>{@link android.media.ImageReader} -
+     * Recommended for image processing or streaming to external resources (such as a file or
+     * network)
+     * <li>{@link android.media.MediaRecorder} -
+     * Recommended for recording video (simple to use)
+     * <li>{@link android.media.MediaCodec} -
+     * Recommended for recording video (more complicated to use, with more flexibility)
+     * <li>{@link android.renderscript.Allocation} -
+     * Recommended for image processing with {@link android.renderscript RenderScript}
+     * <li>{@link android.view.SurfaceHolder} -
+     * Recommended for low-power camera preview with {@link android.view.SurfaceView}
+     * <li>{@link android.graphics.SurfaceTexture} -
+     * Recommended for OpenGL-accelerated preview processing or compositing with
+     * {@link android.view.TextureView}
+     * </ul>
+     * </p>
+     *
+     * <p>Generally speaking this means that creating a {@link Surface} from that class <i>may</i>
+     * provide a producer endpoint that is suitable to be used with
+     * {@link CameraDevice#configureOutputs}.</p>
+     *
+     * <p>Since not all of the above classes support output of all format and size combinations,
+     * the particular combination should be queried with {@link #isOutputSupportedFor(Surface)}.</p>
+     *
+     * @param klass a non-{@code null} {@link Class} object reference
+     * @return {@code true} if this class is supported as an output, {@code false} otherwise
+     *
+     * @throws NullPointerException if {@code klass} was {@code null}
+     *
+     * @see CameraDevice#configureOutputs
+     * @see #isOutputSupportedFor(Surface)
+     */
+    public static <T> boolean isOutputSupportedFor(final Class<T> klass) {
+        checkNotNull(klass, "klass must not be null");
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Determine whether or not the {@code surface} in its current state is suitable to be
+     * {@link CameraDevice#configureOutputs configured} as an output.
+     *
+     * <p>Not all surfaces are usable with the {@link CameraDevice}, and not all configurations
+     * of that {@code surface} are compatible. Some classes that provide the {@code surface} are
+     * compatible with the {@link CameraDevice} in general
+     * (see {@link #isOutputSupportedFor(Class)}, but it is the caller's responsibility to put the
+     * {@code surface} into a state that will be compatible with the {@link CameraDevice}.</p>
+     *
+     * <p>Reasons for a {@code surface} being specifically incompatible might be:
+     * <ul>
+     * <li>Using a format that's not listed by {@link #getOutputFormats}
+     * <li>Using a format/size combination that's not listed by {@link #getOutputSizes}
+     * <li>The {@code surface} itself is not in a state where it can service a new producer.</p>
+     * </li>
+     * </ul>
+     *
+     * This is not an exhaustive list; see the particular class's documentation for further
+     * possible reasons of incompatibility.</p>
+     *
+     * @param surface a non-{@code null} {@link Surface} object reference
+     * @return {@code true} if this is supported, {@code false} otherwise
+     *
+     * @throws NullPointerException if {@code surface} was {@code null}
+     *
+     * @see CameraDevice#configureOutputs
+     * @see #isOutputSupportedFor(Class)
+     */
+    public boolean isOutputSupportedFor(final Surface surface) {
+        checkNotNull(surface, "surface must not be null");
+
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Get a list of sizes compatible with {@code klass} to use as an output.
+     *
+     * <p>Since some of the supported classes may support additional formats beyond
+     * an opaque/implementation-defined (under-the-hood) format; this function only returns
+     * sizes for the implementation-defined format.</p>
+     *
+     * <p>Some classes such as {@link android.media.ImageReader} may only support user-defined
+     * formats; in particular {@link #isOutputSupportedFor(Class)} will return {@code true} for
+     * that class and this method will return an empty array (but not {@code null}).</p>
+     *
+     * <p>If a well-defined format such as {@code NV21} is required, use
+     * {@link #getOutputSizes(int)} instead.</p>
+     *
+     * <p>The {@code klass} should be a supported output, that querying
+     * {@code #isOutputSupportedFor(Class)} should return {@code true}.</p>
+     *
+     * @param klass
+     *          a non-{@code null} {@link Class} object reference
+     * @return
+     *          an array of supported sizes for implementation-defined formats,
+     *          or {@code null} iff the {@code klass} is not a supported output
+     *
+     * @throws NullPointerException if {@code klass} was {@code null}
+     *
+     * @see #isOutputSupportedFor(Class)
+     */
+    public <T> Size[] getOutputSizes(final Class<T> klass) {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Get a list of sizes compatible with the requested image {@code format}.
+     *
+     * <p>The {@code format} should be a supported format (one of the formats returned by
+     * {@link #getOutputFormats}).</p>
+     *
+     * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+     * @return
+     *          an array of supported sizes,
+     *          or {@code null} if the {@code format} is not a supported output
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     * @see #getOutputFormats
+     */
+    public Size[] getOutputSizes(final int format) {
+        try {
+            checkArgumentFormatSupported(format, /*output*/true);
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+     * for the format/size combination (in nanoseconds).
+     *
+     * <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
+     * <p>{@code size} should be one of the ones returned by
+     * {@link #getOutputSizes(int)}.</p>
+     *
+     * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+     * @param size an output-compatible size
+     * @return a minimum frame duration {@code >=} 0 in nanoseconds
+     *
+     * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+     * @throws NullPointerException if {@code size} was {@code null}
+     *
+     * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+     * @see CaptureRequest#SENSOR_FRAME_DURATION
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public long getOutputMinFrameDuration(final int format, final Size size) {
+        checkArgumentFormatSupported(format, /*output*/true);
+
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+     * for the class/size combination (in nanoseconds).
+     *
+     * <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
+     * For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
+     *
+     * <p>{@code klass} should be one of the ones which is supported by
+     * {@link #isOutputSupportedFor(Class)}.</p>
+     *
+     * <p>{@code size} should be one of the ones returned by
+     * {@link #getOutputSizes(int)}.</p>
+     *
+     * @param klass
+     *          a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
+     *          non-empty array returned by {@link #getOutputSizes(Class)}
+     * @param size an output-compatible size
+     * @return a minimum frame duration {@code >=} 0 in nanoseconds
+     *
+     * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+     * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+     *
+     * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+     * @see CaptureRequest#SENSOR_FRAME_DURATION
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public <T> long getOutputMinFrameDuration(final Class<T> klass, final Size size) {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Get the {@link CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS stall duration}
+     * for the format/size combination (in nanoseconds).
+     *
+     * <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
+     * <p>{@code size} should be one of the ones returned by
+     * {@link #getOutputSizes(int)}.</p>
+     *
+     * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+     * @param size an output-compatible size
+     * @return a stall duration {@code >=} 0 in nanoseconds
+     *
+     * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+     * @throws NullPointerException if {@code size} was {@code null}
+     *
+     * @see CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public long getOutputStallDuration(final int format, final Size size) {
+        checkArgumentFormatSupported(format, /*output*/true);
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Get the {@link CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS stall duration}
+     * for the class/size combination (in nanoseconds).
+     *
+     * <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
+     * For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
+     *
+     * <p>{@code klass} should be one of the ones with a non-empty array returned by
+     * {@link #getOutputSizes(Class)}.</p>
+     *
+     * <p>{@code size} should be one of the ones returned by
+     * {@link #getOutputSizes(Class)}.</p>
+     *
+     * @param klass
+     *          a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
+     *          non-empty array returned by {@link #getOutputSizes(Class)}
+     * @param size an output-compatible size
+     * @return a minimum frame duration {@code >=} 0 in nanoseconds
+     *
+     * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+     * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+     *
+     * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+     * @see CaptureRequest#SENSOR_FRAME_DURATION
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public <T> long getOutputStallDuration(final Class<T> klass, final Size size) {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Check if this {@link StreamConfigurationMap} is equal to another
+     * {@link StreamConfigurationMap}.
+     *
+     * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof StreamConfigurationMap) {
+            final StreamConfigurationMap other = (StreamConfigurationMap) obj;
+            // TODO: do we care about order?
+            return Arrays.equals(mConfigurations, other.mConfigurations) &&
+                    Arrays.equals(mDurations, other.mDurations);
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        // TODO: do we care about order?
+        return HashCodeHelpers.hashCode(mConfigurations) ^ HashCodeHelpers.hashCode(mDurations);
+    }
+
+    // Check that the argument is supported by #getOutputFormats or #getInputFormats
+    private int checkArgumentFormatSupported(int format, boolean output) {
+        checkArgumentFormat(format);
+
+        int[] formats = output ? getOutputFormats() : getInputFormats();
+        for (int i = 0; i < formats.length; ++i) {
+            if (format == formats[i]) {
+                return format;
+            }
+        }
+
+        throw new IllegalArgumentException(String.format(
+                "format %x is not supported by this stream configuration map", format));
+    }
+
+    /**
+     * Ensures that the format is either user-defined or implementation defined.
+     *
+     * <p>Any invalid/undefined formats will raise an exception.</p>
+     *
+     * @param format image format
+     * @return the format
+     *
+     * @throws IllegalArgumentException if the format was invalid
+     */
+    static int checkArgumentFormatInternal(int format) {
+        if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+            return format;
+        }
+
+        return checkArgumentFormat(format);
+    }
+
+    /**
+     * Ensures that the format is user-defined in either ImageFormat or PixelFormat.
+     *
+     * <p>Any invalid/undefined formats will raise an exception, including implementation-defined.
+     * </p>
+     *
+     * <p>Note that {@code @hide} and deprecated formats will not pass this check.</p>
+     *
+     * @param format image format
+     * @return the format
+     *
+     * @throws IllegalArgumentException if the format was not user-defined
+     */
+    static int checkArgumentFormat(int format) {
+        if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
+            throw new IllegalArgumentException(String.format(
+                    "format %x was not defined in either ImageFormat or PixelFormat", format));
+        }
+
+        return format;
+    }
+
+    private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
+
+    private final StreamConfiguration[] mConfigurations;
+    private final StreamConfigurationDuration[] mDurations;
+
+}
diff --git a/core/java/android/hardware/camera2/TonemapCurve.java b/core/java/android/hardware/camera2/TonemapCurve.java
new file mode 100644
index 0000000..ee20d68
--- /dev/null
+++ b/core/java/android/hardware/camera2/TonemapCurve.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+
+import android.graphics.PointF;
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class for describing a {@code 2 x M x 3} tonemap curve of floats.
+ *
+ * <p>This defines red, green, and blue curves that the {@link CameraDevice} will
+ * use as the tonemapping/contrast/gamma curve when {@link CaptureRequest#TONEMAP_MODE} is
+ * set to {@link CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE}.</p>
+ *
+ * <p>The total number of points {@code (Pin, Pout)} for each color channel can be no more than
+ * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS}.</p>
+ *
+ * <p>The coordinate system for each point is within the inclusive range
+ * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+ *
+ * @see CaptureRequest#TONEMAP_CURVE_BLUE
+ * @see CaptureRequest#TONEMAP_CURVE_GREEN
+ * @see CaptureRequest#TONEMAP_CURVE_RED
+ * @see CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE
+ * @see CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS
+ */
+public final class TonemapCurve {
+    /**
+     * Lower bound tonemap value corresponding to pure black for a single color channel.
+     */
+    public static final float LEVEL_BLACK = 0.0f;
+
+    /**
+     * Upper bound tonemap value corresponding to a pure white for a single color channel.
+     */
+    public static final float LEVEL_WHITE = 1.0f;
+
+    /**
+     * Number of elements in a {@code (Pin, Pout)} point;
+     */
+    public static final int POINT_SIZE = 2;
+
+    /**
+     * Index of the red color channel curve.
+     */
+    public static final int CHANNEL_RED = 0;
+    /**
+     * Index of the green color channel curve.
+     */
+    public static final int CHANNEL_GREEN = 1;
+    /**
+     * Index of the blue color channel curve.
+     */
+    public static final int CHANNEL_BLUE = 2;
+
+    /**
+     * Create a new immutable TonemapCurve instance.
+     *
+     * <p>Values are stored as a contiguous {@code (Pin, Pout}) point.</p>
+     *
+     * <p>All parameters may have independent length but should have at most
+     * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS} * {@value #POINT_SIZE} elements.</p>
+     *
+     * <p>All sub-elements must be in the inclusive range of
+     * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+     *
+     * <p>This constructor copies the array contents and does not retain ownership of the array.</p>
+     *
+     * @param elements An array of elements whose length is {@code CHANNEL_COUNT * rows * columns}
+     *
+     * @throws IllegalArgumentException
+     *            if the {@code elements} array length is invalid,
+     *            if any of the subelems are not finite
+     * @throws NullPointerException
+     *            if any of the parameters is {@code null}
+     *
+     * @hide
+     */
+    public TonemapCurve(float[] red, float[] green, float[] blue) {
+        // TODO: maxCurvePoints check?
+
+        checkNotNull(red, "red must not be null");
+        checkNotNull(green, "green must not be null");
+        checkNotNull(blue, "blue must not be null");
+
+        checkArgumentArrayLengthDivisibleBy(red, POINT_SIZE, "red");
+        checkArgumentArrayLengthDivisibleBy(green, POINT_SIZE, "green");
+        checkArgumentArrayLengthDivisibleBy(blue, POINT_SIZE, "blue");
+
+        checkArrayElementsInRange(red, LEVEL_BLACK, LEVEL_WHITE, "red");
+        checkArrayElementsInRange(green, LEVEL_BLACK, LEVEL_WHITE, "green");
+        checkArrayElementsInRange(blue, LEVEL_BLACK, LEVEL_WHITE, "blue");
+
+        mRed = Arrays.copyOf(red, red.length);
+        mGreen = Arrays.copyOf(green, green.length);
+        mBlue = Arrays.copyOf(blue, blue.length);
+    }
+
+    private static void checkArgumentArrayLengthDivisibleBy(float[] array,
+            int divisible, String arrayName) {
+        if (array.length % divisible != 0) {
+            throw new IllegalArgumentException(arrayName + " size must be divisible by "
+                    + divisible);
+        }
+    }
+
+    private static int checkArgumentColorChannel(int colorChannel) {
+        switch (colorChannel) {
+            case CHANNEL_RED:
+            case CHANNEL_GREEN:
+            case CHANNEL_BLUE:
+                break;
+            default:
+                throw new IllegalArgumentException("colorChannel out of range");
+        }
+
+        return colorChannel;
+    }
+
+    /**
+     * Get the number of points stored in this tonemap curve for the specified color channel.
+     *
+     * @param colorChannel one of {@link #CHANNEL_RED}, {@link #CHANNEL_GREEN}, {@link #CHANNEL_BLUE}
+     * @return number of points stored in this tonemap for that color's curve (>= 0)
+     *
+     * @throws IllegalArgumentException if {@code colorChannel} was out of range
+     */
+    public int getPointCount(int colorChannel) {
+        checkArgumentColorChannel(colorChannel);
+
+        return getCurve(colorChannel).length / POINT_SIZE;
+    }
+
+    /**
+     * Get the point for a color channel at a specified index.
+     *
+     * <p>The index must be at least 0 but no greater than {@link #getPointCount(int)} for
+     * that {@code colorChannel}.</p>
+     *
+     * <p>All returned coordinates in the point are between the range of
+     * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+     *
+     * @param colorChannel {@link #CHANNEL_RED}, {@link #CHANNEL_GREEN}, or {@link #CHANNEL_BLUE}
+     * @param index at least 0 but no greater than {@code getPointCount(colorChannel)}
+     * @return the {@code (Pin, Pout)} pair mapping the tone for that index
+     *
+     * @throws IllegalArgumentException if {@code colorChannel} or {@code index} was out of range
+     *
+     * @see #LEVEL_BLACK
+     * @see #LEVEL_WHITE
+     */
+    public PointF getPoint(int colorChannel, int index) {
+        checkArgumentColorChannel(colorChannel);
+        if (index < 0 || index >= getPointCount(colorChannel)) {
+            throw new IllegalArgumentException("index out of range");
+        }
+
+        final float[] curve = getCurve(colorChannel);
+
+        final float pIn = curve[index * POINT_SIZE + OFFSET_POINT_IN];
+        final float pOut = curve[index * POINT_SIZE + OFFSET_POINT_OUT];
+
+        return new PointF(pIn, pOut);
+    }
+
+    /**
+     * Copy the color curve for a single color channel from this tonemap curve into the destination.
+     *
+     * <p>
+     * <!--The output is encoded the same as in the constructor -->
+     * Values are stored as packed {@code (Pin, Pout}) points, and there are a total of
+     * {@link #getPointCount} points for that respective channel.</p>
+     *
+     * <p>All returned coordinates are between the range of
+     * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+     *
+     * @param destination
+     *          an array big enough to hold at least {@link #getPointCount} {@code *}
+     *          {@link #POINT_SIZE} elements after the {@code offset}
+     * @param offset
+     *          a non-negative offset into the array
+     * @throws NullPointerException
+     *          If {@code destination} was {@code null}
+     * @throws IllegalArgumentException
+     *          If offset was negative
+     * @throws ArrayIndexOutOfBoundsException
+     *          If there's not enough room to write the elements at the specified destination and
+     *          offset.
+     *
+     * @see CaptureRequest#TONEMAP_CURVE_BLUE
+     * @see CaptureRequest#TONEMAP_CURVE_RED
+     * @see CaptureRequest#TONEMAP_CURVE_GREEN
+     * @see #LEVEL_BLACK
+     * @see #LEVEL_WHITE
+     */
+    public void copyColorCurve(int colorChannel, float[] destination,
+            int offset) {
+        checkArgumentNonnegative(offset, "offset must not be negative");
+        checkNotNull(destination, "destination must not be null");
+
+        if (destination.length + offset < getPointCount(colorChannel) * POINT_SIZE) {
+            throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+        }
+
+        float[] curve = getCurve(colorChannel);
+        System.arraycopy(curve, /*srcPos*/0, destination, offset, curve.length);
+    }
+
+    /**
+     * Check if this TonemapCurve is equal to another TonemapCurve.
+     *
+     * <p>Two matrices are equal if and only if all of their elements are
+     * {@link Object#equals equal}.</p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof TonemapCurve) {
+            final TonemapCurve other = (TonemapCurve) obj;
+            return Arrays.equals(mRed, other.mRed) &&
+                    Arrays.equals(mGreen, other.mGreen) &&
+                    Arrays.equals(mBlue, other.mBlue);
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        if (mHashCalculated) {
+            // Avoid re-calculating hash. Data is immutable so this is both legal and faster.
+            return mHashCode;
+        }
+
+        mHashCode = HashCodeHelpers.hashCode(mRed, mGreen, mBlue);
+        mHashCalculated = true;
+
+        return mHashCode;
+    }
+
+    private float[] getCurve(int colorChannel) {
+        switch (colorChannel) {
+            case CHANNEL_RED:
+                return mRed;
+            case CHANNEL_GREEN:
+                return mGreen;
+            case CHANNEL_BLUE:
+                return mBlue;
+            default:
+                throw new AssertionError("colorChannel out of range");
+        }
+    }
+
+    private final static int OFFSET_POINT_IN = 0;
+    private final static int OFFSET_POINT_OUT = 1;
+
+    private final float[] mRed;
+    private final float[] mGreen;
+    private final float[] mBlue;
+
+    private int mHashCode;
+    private boolean mHashCalculated = false;
+};
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 40a7905..988f8f9 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -647,7 +647,7 @@
                  * should have arrived. The following line checks whether this holds.
                  */
                 if (frameNumber != mCompletedFrameNumber + 1) {
-                    throw new AssertionError(String.format(
+                    Log.e(TAG, String.format(
                             "result frame number %d comes out of order, should be %d + 1",
                             frameNumber, mCompletedFrameNumber));
                 }
diff --git a/core/java/android/hardware/camera2/impl/HashCodeHelpers.java b/core/java/android/hardware/camera2/impl/HashCodeHelpers.java
new file mode 100644
index 0000000..2d63827
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/HashCodeHelpers.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.impl;
+
+/**
+ * Provide hashing functions using the Modified Bernstein hash
+ */
+public final class HashCodeHelpers {
+
+    /**
+     * Hash every element uniformly using the Modified Bernstein hash.
+     *
+     * <p>Useful to implement a {@link Object#hashCode} for uniformly distributed data.</p>
+     *
+     * @param array a non-{@code null} array of integers
+     *
+     * @return the numeric hash code
+     */
+    public static int hashCode(int[] array) {
+        if (array == null) {
+            return 0;
+        }
+
+        /*
+         *  Note that we use 31 here instead of 33 since it's preferred in Effective Java
+         *  and used elsewhere in the runtime (e.g. Arrays#hashCode)
+         *
+         *  That being said 33 and 31 are nearly identical in terms of their usefulness
+         *  according to http://svn.apache.org/repos/asf/apr/apr/trunk/tables/apr_hash.c
+         */
+        int h = 1;
+        for (int x : array) {
+            // Strength reduction; in case the compiler has illusions about divisions being faster
+            h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+        }
+
+        return h;
+    }
+
+    /**
+     * Hash every element uniformly using the Modified Bernstein hash.
+     *
+     * <p>Useful to implement a {@link Object#hashCode} for uniformly distributed data.</p>
+     *
+     * @param array a non-{@code null} array of floats
+     *
+     * @return the numeric hash code
+     */
+    public static int hashCode(float[] array) {
+        if (array == null) {
+            return 0;
+        }
+
+        int h = 1;
+        for (float f : array) {
+            int x = Float.floatToIntBits(f);
+            h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+        }
+
+        return h;
+    }
+
+    /**
+     * Hash every element uniformly using the Modified Bernstein hash.
+     *
+     * <p>Useful to implement a {@link Object#hashCode} for uniformly distributed data.</p>
+     *
+     * @param array a non-{@code null} array of objects
+     *
+     * @return the numeric hash code
+     */
+    public static <T> int hashCode(T[] array) {
+        if (array == null) {
+            return 0;
+        }
+
+        int h = 1;
+        for (T o : array) {
+            int x = (o == null) ? 0 : o.hashCode();
+            h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+        }
+
+        return h;
+    }
+
+    public static <T> int hashCode(T a) {
+        return (a == null) ? 0 : a.hashCode();
+    }
+
+    public static <T> int hashCode(T a, T b) {
+        int h = hashCode(a);
+
+        int x = (b == null) ? 0 : b.hashCode();
+        h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+
+        return h;
+    }
+
+    public static <T> int hashCode(T a, T b, T c) {
+        int h = hashCode(a, b);
+
+        int x = (a == null) ? 0 : a.hashCode();
+        h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+
+        return h;
+    }
+
+    public static int hashCode(int x) {
+        return hashCode(new int[] { x } );
+    }
+
+    public static int hashCode(int x, int y) {
+        return hashCode(new int[] { x, y } );
+    }
+
+    public static int hashCode(int x, int y, int z) {
+        return hashCode(new int[] { x, y, z } );
+    }
+
+    public static int hashCode(int x, int y, int z, int w) {
+        return hashCode(new int[] { x, y, z, w } );
+    }
+
+    public static int hashCode(int x, int y, int z, int w, int t) {
+        return hashCode(new int[] { x, y, z, w, t } );
+    }
+
+
+}
diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java
index 8578a32..7213c78 100644
--- a/core/java/android/hardware/hdmi/HdmiCec.java
+++ b/core/java/android/hardware/hdmi/HdmiCec.java
@@ -85,7 +85,7 @@
     public static final int ADDR_RESERVED_2 = 13;
 
     /** Logical address for TV other than the one assigned with {@link #ADDR_TV} */
-    public static final int ADDR_FREE_USE = 14;
+    public static final int ADDR_SPECIFIC_USE = 14;
 
     /** Logical address for devices to which address cannot be allocated */
     public static final int ADDR_UNREGISTERED = 15;
@@ -160,6 +160,8 @@
     public static final int MESSAGE_SET_EXTERNAL_TIMER = 0xA2;
     public static final int MESSAGE_ABORT = 0xFF;
 
+    public static final int UNKNOWN_VENDOR_ID = 0xFFFFFF;
+
     public static final int POWER_STATUS_UNKNOWN = -1;
     public static final int POWER_STATUS_ON = 0;
     public static final int POWER_STATUS_STANDBY = 1;
@@ -179,6 +181,7 @@
         DEVICE_RECORDER,  // ADDR_RECORDER_3
         DEVICE_TUNER,  // ADDR_TUNER_4
         DEVICE_PLAYBACK,  // ADDR_PLAYBACK_3
+        DEVICE_TV,  // ADDR_SPECIFIC_USE
     };
 
     private static final String[] DEFAULT_NAMES = {
@@ -194,6 +197,7 @@
         "Recorder_3",
         "Tuner_4",
         "Playback_3",
+        "Secondary_TV",
     };
 
     private HdmiCec() { }  // Prevents instantiation.
@@ -221,9 +225,7 @@
      * @return true if the given address is valid
      */
     public static boolean isValidAddress(int address) {
-        // TODO: We leave out the address 'free use(14)' for now. Check this later
-        //       again to make sure it is a valid address for communication.
-        return (ADDR_TV <= address && address <= ADDR_PLAYBACK_3);
+        return (ADDR_TV <= address && address <= ADDR_SPECIFIC_USE);
     }
 
     /**
diff --git a/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java
new file mode 100644
index 0000000..9698445
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.hdmi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class to encapsulate device information for HDMI-CEC. This container
+ * include basic information such as logical address, physical address and
+ * device type, and additional information like vendor id and osd name.
+ */
+public final class HdmiCecDeviceInfo implements Parcelable {
+    // Logical address, phsical address, device type, vendor id and display name
+    // are immutable value.
+    private final int mLogicalAddress;
+    private final int mPhysicalAddress;
+    private final int mDeviceType;
+    private final int mVendorId;
+    private final String mDisplayName;
+
+
+    /**
+     * A helper class to deserialize {@link HdmiCecDeviceInfo} for a parcel.
+     */
+    public static final Parcelable.Creator<HdmiCecDeviceInfo> CREATOR =
+            new Parcelable.Creator<HdmiCecDeviceInfo>() {
+                @Override
+                public HdmiCecDeviceInfo createFromParcel(Parcel source) {
+                    int logicalAddress = source.readInt();
+                    int physicalAddress = source.readInt();
+                    int deviceType = source.readInt();
+                    int vendorId = source.readInt();
+                    String displayName = source.readString();
+                    return new HdmiCecDeviceInfo(logicalAddress, physicalAddress, deviceType,
+                            vendorId, displayName);
+                }
+
+                @Override
+                public HdmiCecDeviceInfo[] newArray(int size) {
+                    return new HdmiCecDeviceInfo[size];
+                }
+            };
+
+    /**
+     * Constructor.
+     *
+     * @param logicalAddress logical address of HDMI-Cec device.
+     *                       For more details, refer {@link HdmiCec}
+     * @param physicalAddress physical address of HDMI-Cec device
+     * @param deviceType type of device. For more details, refer {@link HdmiCec}
+     * @param vendorId vendor id of device. It's used for vendor specific command
+     * @param displayName name of device
+     * @hide
+     */
+    public HdmiCecDeviceInfo(int logicalAddress, int physicalAddress, int deviceType,
+            int vendorId, String displayName) {
+        mLogicalAddress = logicalAddress;
+        mPhysicalAddress = physicalAddress;
+        mDeviceType = deviceType;
+        mDisplayName = displayName;
+        mVendorId = vendorId;
+    }
+
+    /**
+     * Return the logical address of the device. It can have 0-15 values.
+     * For more details, refer constants between {@link HdmiCec#ADDR_TV}
+     * and {@link HdmiCec#ADDR_UNREGISTERED}.
+     */
+    public int getLogicalAddress() {
+        return mLogicalAddress;
+    }
+
+    /**
+     * Return the physical address of the device.
+     */
+    public int getPhysicalAddress() {
+        return mPhysicalAddress;
+    }
+
+    /**
+     * Return type of the device. For more details, refer constants between
+     * {@link HdmiCec#DEVICE_TV} and {@link HdmiCec#DEVICE_INACTIVE}.
+     */
+    public int getDeviceType() {
+        return mDeviceType;
+    }
+
+    /**
+     * Return display (OSD) name of the device.
+     */
+    public String getDisplayName() {
+        return mDisplayName;
+    }
+
+    /**
+     * Return vendor id of the device. Vendor id is used to distinguish devices
+     * built by other manufactures. This is required for vendor-specific command
+     * on CEC standard.
+     */
+    public int getVendorId() {
+        return mVendorId;
+    }
+
+    /**
+     * Describe the kinds of special objects contained in this Parcelable's
+     * marshalled representation.
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Serialize this object into a {@link Parcel}.
+     *
+     * @param dest The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written.
+     *        May be 0 or {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE}.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mLogicalAddress);
+        dest.writeInt(mPhysicalAddress);
+        dest.writeInt(mDeviceType);
+        dest.writeInt(mVendorId);
+        dest.writeString(mDisplayName);
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer s = new StringBuffer();
+        s.append("logical_address: ").append(mLogicalAddress).append(", ");
+        s.append("physical_address: ").append(mPhysicalAddress).append(", ");
+        s.append("device_type: ").append(mDeviceType).append(", ");
+        s.append("vendor_id: ").append(mVendorId).append(", ");
+        s.append("display_name: ").append(mDisplayName);
+        return s.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof HdmiCecDeviceInfo)) {
+            return false;
+        }
+
+        HdmiCecDeviceInfo other = (HdmiCecDeviceInfo) obj;
+        return mLogicalAddress == other.mLogicalAddress
+                && mPhysicalAddress == other.mPhysicalAddress
+                && mDeviceType == other.mDeviceType
+                && mVendorId == other.mVendorId
+                && mDisplayName.equals(other.mDisplayName);
+    }
+}
diff --git a/core/java/android/hardware/hdmi/HdmiCecMessage.java b/core/java/android/hardware/hdmi/HdmiCecMessage.java
index be94d97..ddaf870 100644
--- a/core/java/android/hardware/hdmi/HdmiCecMessage.java
+++ b/core/java/android/hardware/hdmi/HdmiCecMessage.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import libcore.util.EmptyArray;
+
 import java.util.Arrays;
 
 /**
@@ -28,6 +30,8 @@
  */
 public final class HdmiCecMessage implements Parcelable {
 
+    public static final byte[] EMPTY_PARAM = EmptyArray.BYTE;
+
     private static final int MAX_MESSAGE_LENGTH = 16;
 
     private final int mSource;
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 505ef9c..4160633 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -654,19 +654,18 @@
         return false;
     }
 
-    @Override public void onCreate() {
-        mTheme = Resources.selectSystemTheme(mTheme,
-                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);
+    @Override
+    public void onCreate() {
+        mTheme = getResources().selectSystemTheme(mTheme, getApplicationInfo().targetSdkVersion,
+                com.android.internal.R.array.system_theme_sdks,
+                com.android.internal.R.array.system_theme_ime_styles);
         super.setTheme(mTheme);
         super.onCreate();
         mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
         mInflater = (LayoutInflater)getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
-        mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
+        mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
+                false);
         if (mHardwareAccelerated) {
             mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
         }
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index df1afee..a9bace1 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -30,11 +30,20 @@
  * method window.  It will be displayed along the edge of the screen, moving
  * the application user interface away from it so that the focused item is
  * always visible.
+ * @hide
  */
-class SoftInputWindow extends Dialog {
+public class SoftInputWindow extends Dialog {
+    final String mName;
+    final Callback mCallback;
+    final KeyEvent.Callback mKeyEventCallback;
     final KeyEvent.DispatcherState mDispatcherState;
+    final boolean mTakesFocus;
     private final Rect mBounds = new Rect();
-    
+
+    public interface Callback {
+        public void onBackPressed();
+    }
+
     public void setToken(IBinder token) {
         WindowManager.LayoutParams lp = getWindow().getAttributes();
         lp.token = token;
@@ -53,10 +62,15 @@
      *        using styles. This theme is applied on top of the current theme in
      *        <var>context</var>. If 0, the default dialog theme will be used.
      */
-    public SoftInputWindow(Context context, int theme,
-            KeyEvent.DispatcherState dispatcherState) {
+    public SoftInputWindow(Context context, String name, int theme, Callback callback,
+            KeyEvent.Callback keyEventCallback, KeyEvent.DispatcherState dispatcherState,
+            boolean takesFocus) {
         super(context, theme);
+        mName = name;
+        mCallback = callback;
+        mKeyEventCallback = keyEventCallback;
         mDispatcherState = dispatcherState;
+        mTakesFocus = takesFocus;
         initDockWindow();
     }
 
@@ -148,11 +162,47 @@
         }
     }
 
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (mKeyEventCallback != null && mKeyEventCallback.onKeyDown(keyCode, event)) {
+            return true;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+        if (mKeyEventCallback != null && mKeyEventCallback.onKeyLongPress(keyCode, event)) {
+            return true;
+        }
+        return super.onKeyLongPress(keyCode, event);
+    }
+
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (mKeyEventCallback != null && mKeyEventCallback.onKeyUp(keyCode, event)) {
+            return true;
+        }
+        return super.onKeyUp(keyCode, event);
+    }
+
+    public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
+        if (mKeyEventCallback != null && mKeyEventCallback.onKeyMultiple(keyCode, count, event)) {
+            return true;
+        }
+        return super.onKeyMultiple(keyCode, count, event);
+    }
+
+    public void onBackPressed() {
+        if (mCallback != null) {
+            mCallback.onBackPressed();
+        } else {
+            super.onBackPressed();
+        }
+    }
+
     private void initDockWindow() {
         WindowManager.LayoutParams lp = getWindow().getAttributes();
 
         lp.type = WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-        lp.setTitle("InputMethod");
+        lp.setTitle(mName);
 
         lp.gravity = Gravity.BOTTOM;
         lp.width = -1;
@@ -161,11 +211,19 @@
         //lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
 
         getWindow().setAttributes(lp);
-        getWindow().setFlags(
-                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
-                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
+
+        int windowSetFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+        int windowModFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
-                WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+                WindowManager.LayoutParams.FLAG_DIM_BEHIND;
+
+        if (!mTakesFocus) {
+            windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        } else {
+            windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+            windowModFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+        }
+
+        getWindow().setFlags(windowSetFlags, windowModFlags);
     }
 }
diff --git a/core/java/android/net/INetworkScoreCache.aidl b/core/java/android/net/INetworkScoreCache.aidl
new file mode 100644
index 0000000..35601ce
--- /dev/null
+++ b/core/java/android/net/INetworkScoreCache.aidl
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.ScoredNetwork;
+
+/**
+ * A service which stores a subset of scored networks from the active network scorer.
+ *
+ * <p>To be implemented by network subsystems (e.g. Wi-Fi). NetworkScoreService will propagate
+ * scores down to each subsystem depending on the network type. Implementations may register for
+ * a given network type by calling NetworkScoreManager.registerNetworkSubsystem.
+ *
+ * <p>A proper implementation should throw SecurityException whenever the caller is not privileged.
+ * It may request scores by calling NetworkScoreManager#requestScores(NetworkKey[]); a call to
+ * updateScores may follow but may not depending on the active scorer's implementation, and in
+ * general this method may be called at any time.
+ *
+ * <p>Implementations should also override dump() so that "adb shell dumpsys network_score" includes
+ * the current scores for each network for debugging purposes.
+ * @hide
+ */
+interface INetworkScoreCache
+{
+    void updateScores(in List<ScoredNetwork> networks);
+
+    void clearScores();
+}
+
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index a72d9a0..626bd2a 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.net.INetworkScoreCache;
 import android.net.ScoredNetwork;
 
 /**
@@ -34,8 +35,7 @@
     /**
      * Clear all scores.
      * @return whether the clear was successful.
-     * @throws SecurityException if the caller is neither the current active scorer nor the scorer
-     * manager.
+     * @throws SecurityException if the caller is neither the current active scorer nor the system.
      */
     boolean clearScores();
 
@@ -43,7 +43,19 @@
      * Set the active scorer and clear existing scores.
      * @param packageName the package name of the new scorer to use.
      * @return true if the operation succeeded, or false if the new package is not a valid scorer.
-     * @throws SecurityException if the caller is not the scorer manager.
+     * @throws SecurityException if the caller is not the system.
      */
     boolean setActiveScorer(in String packageName);
+
+    /**
+     * Register a network subsystem for scoring.
+     *
+     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
+     * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
+     * @throws SecurityException if the caller is not the system.
+     * @throws IllegalArgumentException if a score cache is already registed for this type.
+     * @hide
+     */
+    void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache);
+
 }
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 6dd56d9..352512e 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -19,6 +19,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
+import android.content.Intent;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -101,7 +102,7 @@
      * determine the current scorer and offer the user the ability to select a different scorer via
      * the {@link #ACTION_CHANGE_ACTIVE} intent.
      * @return the full package name of the current active scorer, or null if there is no active
-     *     scorer.
+     *         scorer.
      */
     public String getActiveScorerPackage() {
         return NetworkScorerAppManager.getActiveScorer(mContext);
@@ -151,8 +152,8 @@
      *
      * @return true if the operation succeeded, or false if the new package is not a valid scorer.
      * @throws SecurityException if the caller does not hold the
-     *      {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission indicating that
-     *      it can manage scorer applications.
+     *         {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission indicating
+     *         that it can manage scorer applications.
      * @hide
      */
     public boolean setActiveScorer(String packageName) throws SecurityException {
@@ -162,4 +163,44 @@
             return false;
         }
     }
+
+    /**
+     * Request scoring for networks.
+     *
+     * <p>Note that this is just a helper method to assemble the broadcast, and will run in the
+     * calling process.
+     *
+     * @return true if the broadcast was sent, or false if there is no active scorer.
+     * @throws SecurityException if the caller does not hold the
+     *         {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+     * @hide
+     */
+    public boolean requestScores(NetworkKey[] networks) throws SecurityException {
+        String activeScorer = getActiveScorerPackage();
+        if (activeScorer == null) {
+            return false;
+        }
+        Intent intent = new Intent(ACTION_SCORE_NETWORKS);
+        intent.setPackage(activeScorer);
+        intent.putExtra(EXTRA_NETWORKS_TO_SCORE, networks);
+        mContext.sendBroadcast(intent);
+        return true;
+    }
+
+    /**
+     * Register a network score cache.
+     *
+     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
+     * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
+     * @throws SecurityException if the caller does not hold the
+     *         {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+     * @throws IllegalArgumentException if a score cache is already registered for this type.
+     * @hide
+     */
+    public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+        try {
+            mService.registerNetworkScoreCache(networkType, scoreCache);
+        } catch (RemoteException e) {
+        }
+    }
 }
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 033332c..bea8d1c 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -274,48 +274,6 @@
         return PROXY_VALID;
     }
 
-    static class AndroidProxySelectorRoutePlanner
-            extends org.apache.http.impl.conn.ProxySelectorRoutePlanner {
-
-        private Context mContext;
-
-        public AndroidProxySelectorRoutePlanner(SchemeRegistry schreg, ProxySelector prosel,
-                Context context) {
-            super(schreg, prosel);
-            mContext = context;
-        }
-
-        @Override
-        protected java.net.Proxy chooseProxy(List<java.net.Proxy> proxies, HttpHost target,
-                HttpRequest request, HttpContext context) {
-            return getProxy(mContext, target.getHostName());
-        }
-
-        @Override
-        protected HttpHost determineProxy(HttpHost target, HttpRequest request,
-                HttpContext context) {
-            return getPreferredHttpHost(mContext, target.getHostName());
-        }
-
-        @Override
-        public HttpRoute determineRoute(HttpHost target, HttpRequest request,
-                HttpContext context) {
-            HttpHost proxy = getPreferredHttpHost(mContext, target.getHostName());
-            if (proxy == null) {
-                return new HttpRoute(target);
-            } else {
-                return new HttpRoute(target, null, proxy, false);
-            }
-        }
-    }
-
-    /** @hide */
-    public static final HttpRoutePlanner getAndroidProxySelectorRoutePlanner(Context context) {
-        AndroidProxySelectorRoutePlanner ret = new AndroidProxySelectorRoutePlanner(
-                new SchemeRegistry(), ProxySelector.getDefault(), context);
-        return ret;
-    }
-
     /** @hide */
     public static final void setHttpProxySystemProperty(ProxyProperties p) {
         String host = null;
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
index 33e81c2..dd744d3 100644
--- a/core/java/android/net/RssiCurve.java
+++ b/core/java/android/net/RssiCurve.java
@@ -98,6 +98,27 @@
     }
 
     /**
+     * Lookup the score for a given RSSI value.
+     *
+     * @param rssi The RSSI to lookup. If the RSSI falls below the start of the curve, the score at
+     *         the start of the curve will be returned. If it falls after the end of the curve, the
+     *         score at the end of the curve will be returned.
+     * @return the score for the given RSSI.
+     */
+    public byte lookupScore(int rssi) {
+        int index = (rssi - start) / bucketWidth;
+
+        // Snap the index to the closest bucket if it falls outside the curve.
+        if (index < 0) {
+            index = 0;
+        } else if (index > rssiBuckets.length - 1) {
+            index = rssiBuckets.length - 1;
+        }
+
+        return rssiBuckets[index];
+    }
+
+    /**
      * Determine if two RSSI curves are defined in the same way.
      *
      * <p>Note that two curves can be equivalent but defined differently, e.g. if one bucket in one
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9e9820f..f1ad1f8 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -175,6 +175,8 @@
     private static final String POWER_USE_ITEM_DATA = "pwi";
     private static final String DISCHARGE_STEP_DATA = "dsd";
     private static final String CHARGE_STEP_DATA = "csd";
+    private static final String DISCHARGE_TIME_REMAIN_DATA = "dtr";
+    private static final String CHARGE_TIME_REMAIN_DATA = "ctr";
 
     private final StringBuilder mFormatBuilder = new StringBuilder(32);
     private final Formatter mFormatter = new Formatter(mFormatBuilder);
@@ -3076,7 +3078,7 @@
                         HISTORY_STATE2_DESCRIPTIONS, !checkin);
                 if (rec.wakeReasonTag != null) {
                     if (checkin) {
-                        pw.print(",Wr=");
+                        pw.print(",wr=");
                         pw.print(rec.wakeReasonTag.poolIdx);
                     } else {
                         pw.print(" wake_reason=");
@@ -3423,8 +3425,21 @@
         if (!filtering) {
             dumpDurationSteps(pw, DISCHARGE_STEP_DATA, getDischargeStepDurationsArray(),
                     getNumDischargeStepDurations(), true);
+            String[] lineArgs = new String[1];
+            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
+            if (timeRemaining >= 0) {
+                lineArgs[0] = Long.toString(timeRemaining);
+                dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
+                        (Object[])lineArgs);
+            }
             dumpDurationSteps(pw, CHARGE_STEP_DATA, getChargeStepDurationsArray(),
                     getNumChargeStepDurations(), true);
+            timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
+            if (timeRemaining >= 0) {
+                lineArgs[0] = Long.toString(timeRemaining);
+                dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
+                        (Object[])lineArgs);
+            }
         }
         if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index c3f7370..899a958 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -29,6 +29,7 @@
 interface IUserManager {
     UserInfo createUser(in String name, int flags);
     UserInfo createProfileForUser(in String name, int flags, int userHandle);
+    void setUserEnabled(int userHandle);
     boolean removeUser(int userHandle);
     void setUserName(int userHandle, String name);
     void setUserIcon(int userHandle, in Bitmap icon);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 1fe9337..1b2b798 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -437,6 +437,22 @@
     }
 
     /**
+     * Sets the user as enabled, if such an user exists.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * Note that the default is true, it's only that managed profiles might not be enabled.
+     *
+     * @param userHandle the id of the profile to enable
+     * @hide
+     */
+    public void setUserEnabled(int userHandle) {
+        try {
+            mService.setUserEnabled(userHandle);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Could not enable the profile", e);
+        }
+    }
+
+    /**
      * Return the number of users currently created on the device.
      */
     public int getUserCount() {
@@ -488,8 +504,7 @@
         ArrayList<UserHandle> profiles = new ArrayList<UserHandle>();
         List<UserInfo> users = new ArrayList<UserInfo>();
         try {
-            // TODO: Switch enabledOnly to true once client apps are updated
-            users = mService.getProfiles(UserHandle.myUserId(), false /* enabledOnly */);
+            users = mService.getProfiles(UserHandle.myUserId(), true /* enabledOnly */);
         } catch (RemoteException re) {
             Log.w(TAG, "Could not get user list", re);
             return null;
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 71e3166..aa724f0 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -41,16 +41,25 @@
     public static final int FLAG_RELEVANT_ALWAYS = 1 << 1;
 
     public final Uri id;
-    public String caption;
-    public int state;
-    public int flags;
+    public final String summary;
+    public final String line1;
+    public final String line2;
+    public final int icon;
+    public final int state;
+    public final int flags;
 
-    public Condition(Uri id, String caption, int state, int flags) {
+    public Condition(Uri id, String summary, String line1, String line2, int icon,
+            int state, int flags) {
         if (id == null) throw new IllegalArgumentException("id is required");
-        if (caption == null) throw new IllegalArgumentException("caption is required");
+        if (summary == null) throw new IllegalArgumentException("summary is required");
+        if (line1 == null) throw new IllegalArgumentException("line1 is required");
+        if (line2 == null) throw new IllegalArgumentException("line2 is required");
         if (!isValidState(state)) throw new IllegalArgumentException("state is invalid: " + state);
         this.id = id;
-        this.caption = caption;
+        this.summary = summary;
+        this.line1 = line1;
+        this.line2 = line2;
+        this.icon = icon;
         this.state = state;
         this.flags = flags;
     }
@@ -58,6 +67,9 @@
     private Condition(Parcel source) {
         this((Uri)source.readParcelable(Condition.class.getClassLoader()),
                 source.readString(),
+                source.readString(),
+                source.readString(),
+                source.readInt(),
                 source.readInt(),
                 source.readInt());
     }
@@ -69,16 +81,22 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(id, 0);
-        dest.writeString(caption);
+        dest.writeString(summary);
+        dest.writeString(line1);
+        dest.writeString(line2);
+        dest.writeInt(icon);
         dest.writeInt(state);
-        dest.writeInt(flags);
+        dest.writeInt(this.flags);
     }
 
     @Override
     public String toString() {
         return new StringBuilder(Condition.class.getSimpleName()).append('[')
             .append("id=").append(id)
-            .append(",caption=").append(caption)
+            .append(",summary=").append(summary)
+            .append(",line1=").append(line1)
+            .append(",line2=").append(line2)
+            .append(",icon=").append(icon)
             .append(",state=").append(stateToString(state))
             .append(",flags=").append(flags)
             .append(']').toString();
@@ -92,20 +110,31 @@
         throw new IllegalArgumentException("state is invalid: " + state);
     }
 
+    public static String relevanceToString(int flags) {
+        final boolean now = (flags & FLAG_RELEVANT_NOW) != 0;
+        final boolean always = (flags & FLAG_RELEVANT_ALWAYS) != 0;
+        if (!now && !always) return "NONE";
+        if (now && always) return "NOW, ALWAYS";
+        return now ? "NOW" : "ALWAYS";
+    }
+
     @Override
     public boolean equals(Object o) {
         if (!(o instanceof Condition)) return false;
         if (o == this) return true;
         final Condition other = (Condition) o;
         return Objects.equals(other.id, id)
-                && Objects.equals(other.caption, caption)
+                && Objects.equals(other.summary, summary)
+                && Objects.equals(other.line1, line1)
+                && Objects.equals(other.line2, line2)
+                && other.icon == icon
                 && other.state == state
                 && other.flags == flags;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(id, caption, state, flags);
+        return Objects.hash(id, summary, line1, line2, icon, state, flags);
     }
 
     @Override
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 925ddcf..846e292 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -16,6 +16,8 @@
 
 package android.service.notification;
 
+import android.content.ComponentName;
+import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -25,6 +27,8 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -51,6 +55,10 @@
     private static final String SLEEP_ATT_END_HR = "endHour";
     private static final String SLEEP_ATT_END_MIN = "endMin";
 
+    private static final String CONDITION_TAG = "condition";
+    private static final String CONDITION_ATT_COMPONENT = "component";
+    private static final String CONDITION_ATT_ID = "id";
+
     public boolean allowCalls;
     public boolean allowMessages;
 
@@ -59,6 +67,8 @@
     public int sleepStartMinute;
     public int sleepEndHour;
     public int sleepEndMinute;
+    public ComponentName[] conditionComponents;
+    public Uri[] conditionIds;
 
     public ZenModeConfig() { }
 
@@ -72,6 +82,16 @@
         sleepStartMinute = source.readInt();
         sleepEndHour = source.readInt();
         sleepEndMinute = source.readInt();
+        int len = source.readInt();
+        if (len > 0) {
+            conditionComponents = new ComponentName[len];
+            source.readTypedArray(conditionComponents, ComponentName.CREATOR);
+        }
+        len = source.readInt();
+        if (len > 0) {
+            conditionIds = new Uri[len];
+            source.readTypedArray(conditionIds, Uri.CREATOR);
+        }
     }
 
     @Override
@@ -88,6 +108,18 @@
         dest.writeInt(sleepStartMinute);
         dest.writeInt(sleepEndHour);
         dest.writeInt(sleepEndMinute);
+        if (conditionComponents != null && conditionComponents.length > 0) {
+            dest.writeInt(conditionComponents.length);
+            dest.writeTypedArray(conditionComponents, 0);
+        } else {
+            dest.writeInt(0);
+        }
+        if (conditionIds != null && conditionIds.length > 0) {
+            dest.writeInt(conditionIds.length);
+            dest.writeTypedArray(conditionIds, 0);
+        } else {
+            dest.writeInt(0);
+        }
     }
 
     @Override
@@ -98,6 +130,10 @@
             .append(",sleepMode=").append(sleepMode)
             .append(",sleepStart=").append(sleepStartHour).append('.').append(sleepStartMinute)
             .append(",sleepEnd=").append(sleepEndHour).append('.').append(sleepEndMinute)
+            .append(",conditionComponents=")
+            .append(conditionComponents == null ? null : TextUtils.join(",", conditionComponents))
+            .append(",conditionIds=")
+            .append(conditionIds == null ? null : TextUtils.join(",", conditionIds))
             .append(']').toString();
     }
 
@@ -112,13 +148,16 @@
                 && other.sleepStartHour == sleepStartHour
                 && other.sleepStartMinute == sleepStartMinute
                 && other.sleepEndHour == sleepEndHour
-                && other.sleepEndMinute == sleepEndMinute;
+                && other.sleepEndMinute == sleepEndMinute
+                && Objects.deepEquals(other.conditionComponents, conditionComponents)
+                && Objects.deepEquals(other.conditionIds, conditionIds);
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(allowCalls, allowMessages, sleepMode, sleepStartHour,
-                sleepStartMinute, sleepEndHour, sleepEndMinute);
+                sleepStartMinute, sleepEndHour, sleepEndMinute,
+                Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds));
     }
 
     public boolean isValid() {
@@ -136,9 +175,18 @@
         if (!ZEN_TAG.equals(tag)) return null;
         final ZenModeConfig rt = new ZenModeConfig();
         final int version = Integer.parseInt(parser.getAttributeValue(null, ZEN_ATT_VERSION));
+        final ArrayList<ComponentName> conditionComponents = new ArrayList<ComponentName>();
+        final ArrayList<Uri> conditionIds = new ArrayList<Uri>();
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
             tag = parser.getName();
-            if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) return rt;
+            if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) {
+                if (!conditionComponents.isEmpty()) {
+                    rt.conditionComponents = conditionComponents
+                            .toArray(new ComponentName[conditionComponents.size()]);
+                    rt.conditionIds = conditionIds.toArray(new Uri[conditionIds.size()]);
+                }
+                return rt;
+            }
             if (type == XmlPullParser.START_TAG) {
                 if (ALLOW_TAG.equals(tag)) {
                     rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS, false);
@@ -155,10 +203,18 @@
                     rt.sleepStartMinute = isValidMinute(startMinute) ? startMinute : 0;
                     rt.sleepEndHour = isValidHour(endHour) ? endHour : 0;
                     rt.sleepEndMinute = isValidMinute(endMinute) ? endMinute : 0;
+                } else if (CONDITION_TAG.equals(tag)) {
+                    final ComponentName component =
+                            safeComponentName(parser, CONDITION_ATT_COMPONENT);
+                    final Uri conditionId = safeUri(parser, CONDITION_ATT_ID);
+                    if (component != null && conditionId != null) {
+                        conditionComponents.add(component);
+                        conditionIds.add(conditionId);
+                    }
                 }
             }
         }
-        return rt;
+        throw new IllegalStateException("Failed to reach END_DOCUMENT");
     }
 
     public void writeXml(XmlSerializer out) throws IOException {
@@ -180,6 +236,16 @@
         out.attribute(null, SLEEP_ATT_END_MIN, Integer.toString(sleepEndMinute));
         out.endTag(null, SLEEP_TAG);
 
+        if (conditionComponents != null && conditionIds != null
+                && conditionComponents.length == conditionIds.length) {
+            for (int i = 0; i < conditionComponents.length; i++) {
+                out.startTag(null, CONDITION_TAG);
+                out.attribute(null, CONDITION_ATT_COMPONENT,
+                        conditionComponents[i].flattenToString());
+                out.attribute(null, CONDITION_ATT_ID, conditionIds[i].toString());
+                out.endTag(null, CONDITION_TAG);
+            }
+        }
         out.endTag(null, ZEN_TAG);
     }
 
@@ -203,6 +269,18 @@
         return Integer.valueOf(val);
     }
 
+    private static ComponentName safeComponentName(XmlPullParser parser, String att) {
+        final String val = parser.getAttributeValue(null, att);
+        if (TextUtils.isEmpty(val)) return null;
+        return ComponentName.unflattenFromString(val);
+    }
+
+    private static Uri safeUri(XmlPullParser parser, String att) {
+        final String val = parser.getAttributeValue(null, att);
+        if (TextUtils.isEmpty(val)) return null;
+        return Uri.parse(val);
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/core/java/android/service/voice/IVoiceInteractionSession.aidl b/core/java/android/service/voice/IVoiceInteractionSession.aidl
index 7dbf66b..9f9c312 100644
--- a/core/java/android/service/voice/IVoiceInteractionSession.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl
@@ -16,13 +16,14 @@
 
 package android.service.voice;
 
-import android.os.Bundle;
-
-import com.android.internal.app.IVoiceInteractorCallback;
-import com.android.internal.app.IVoiceInteractorRequest;
+import android.content.Intent;
 
 /**
  * @hide
  */
-interface IVoiceInteractionSession {
+oneway interface IVoiceInteractionSession {
+    void taskStarted(in Intent intent, int taskId);
+    void taskFinished(in Intent intent, int taskId);
+    void closeSystemDialogs();
+    void destroy();
 }
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index d005890..e15489b 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -27,6 +27,19 @@
 import android.os.ServiceManager;
 import com.android.internal.app.IVoiceInteractionManagerService;
 
+/**
+ * Top-level service of the current global voice interactor, which is providing
+ * support for hotwording, the back-end of a {@link android.app.VoiceInteractor}, etc.
+ * The current VoiceInteractionService that has been selected by the user is kept
+ * always running by the system, to allow it to do things like listen for hotwords
+ * in the background to instigate voice interactions.
+ *
+ * <p>Because this service is always running, it should be kept as lightweight as
+ * possible.  Heavy-weight operations (including showing UI) should be implemented
+ * in the associated {@link android.service.voice.VoiceInteractionSessionService} when
+ * an actual voice interaction is taking place, and that service should run in a
+ * separate process from this one.
+ */
 public class VoiceInteractionService extends Service {
     /**
      * The {@link Intent} that must be declared as handled by the service.
@@ -51,11 +64,9 @@
 
     IVoiceInteractionManagerService mSystemService;
 
-    public void startVoiceActivity(Intent intent, Bundle sessionArgs) {
+    public void startSession(Bundle args) {
         try {
-            mSystemService.startVoiceActivity(intent,
-                    intent.resolveType(getContentResolver()),
-                    mInterface, sessionArgs);
+            mSystemService.startSession(mInterface, args);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 963b6b4..a83544d 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -16,7 +16,14 @@
 
 package android.service.voice;
 
+import android.app.Dialog;
+import android.app.Instrumentation;
 import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Region;
+import android.inputmethodservice.SoftInputWindow;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -25,16 +32,53 @@
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import com.android.internal.app.IVoiceInteractionManagerService;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.IVoiceInteractorCallback;
 import com.android.internal.app.IVoiceInteractorRequest;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 
-public abstract class VoiceInteractionSession {
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+public abstract class VoiceInteractionSession implements KeyEvent.Callback {
     static final String TAG = "VoiceInteractionSession";
     static final boolean DEBUG = true;
 
+    final Context mContext;
+    final HandlerCaller mHandlerCaller;
+
+    final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState();
+
+    IVoiceInteractionManagerService mSystemService;
+    IBinder mToken;
+
+    int mTheme = 0;
+    LayoutInflater mInflater;
+    TypedArray mThemeAttrs;
+    View mRootView;
+    FrameLayout mContentFrame;
+    SoftInputWindow mWindow;
+
+    boolean mInitialized;
+    boolean mWindowAdded;
+    boolean mWindowVisible;
+    boolean mWindowWasVisible;
+    boolean mInShowWindow;
+
+    final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
+
+    final Insets mTmpInsets = new Insets();
+    final int[] mTmpLocation = new int[2];
+
     final IVoiceInteractor mInteractor = new IVoiceInteractor.Stub() {
         @Override
         public IVoiceInteractorRequest startConfirmation(String callingPackage,
@@ -71,6 +115,27 @@
     };
 
     final IVoiceInteractionSession mSession = new IVoiceInteractionSession.Stub() {
+        @Override
+        public void taskStarted(Intent intent, int taskId) {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIO(MSG_TASK_STARTED,
+                    taskId, intent));
+        }
+
+        @Override
+        public void taskFinished(Intent intent, int taskId) {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIO(MSG_TASK_FINISHED,
+                    taskId, intent));
+        }
+
+        @Override
+        public void closeSystemDialogs() {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_CLOSE_SYSTEM_DIALOGS));
+        }
+
+        @Override
+        public void destroy() {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_DESTROY));
+        }
     };
 
     public static class Request {
@@ -129,38 +194,128 @@
     static final int MSG_SUPPORTS_COMMANDS = 3;
     static final int MSG_CANCEL = 4;
 
-    final Context mContext;
-    final HandlerCaller mHandlerCaller;
-    final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
+    static final int MSG_TASK_STARTED = 100;
+    static final int MSG_TASK_FINISHED = 101;
+    static final int MSG_CLOSE_SYSTEM_DIALOGS = 102;
+    static final int MSG_DESTROY = 103;
+
+    class MyCallbacks implements HandlerCaller.Callback, SoftInputWindow.Callback {
         @Override
         public void executeMessage(Message msg) {
-            SomeArgs args = (SomeArgs)msg.obj;
+            SomeArgs args;
             switch (msg.what) {
                 case MSG_START_CONFIRMATION:
+                    args = (SomeArgs)msg.obj;
                     if (DEBUG) Log.d(TAG, "onConfirm: req=" + ((Request) args.arg2).mInterface
                             + " prompt=" + args.arg3 + " extras=" + args.arg4);
                     onConfirm((Caller)args.arg1, (Request)args.arg2, (String)args.arg3,
                             (Bundle)args.arg4);
                     break;
                 case MSG_START_COMMAND:
+                    args = (SomeArgs)msg.obj;
                     if (DEBUG) Log.d(TAG, "onCommand: req=" + ((Request) args.arg2).mInterface
                             + " command=" + args.arg3 + " extras=" + args.arg4);
                     onCommand((Caller) args.arg1, (Request) args.arg2, (String) args.arg3,
                             (Bundle) args.arg4);
                     break;
                 case MSG_SUPPORTS_COMMANDS:
+                    args = (SomeArgs)msg.obj;
                     if (DEBUG) Log.d(TAG, "onGetSupportedCommands: cmds=" + args.arg2);
                     args.arg1 = onGetSupportedCommands((Caller) args.arg1, (String[]) args.arg2);
                     break;
                 case MSG_CANCEL:
+                    args = (SomeArgs)msg.obj;
                     if (DEBUG) Log.d(TAG, "onCancel: req=" + ((Request) args.arg1).mInterface);
                     onCancel((Request)args.arg1);
                     break;
+                case MSG_TASK_STARTED:
+                    if (DEBUG) Log.d(TAG, "onTaskStarted: intent=" + msg.obj
+                            + " taskId=" + msg.arg1);
+                    onTaskStarted((Intent) msg.obj, msg.arg1);
+                    break;
+                case MSG_TASK_FINISHED:
+                    if (DEBUG) Log.d(TAG, "onTaskFinished: intent=" + msg.obj
+                            + " taskId=" + msg.arg1);
+                    onTaskFinished((Intent) msg.obj, msg.arg1);
+                    break;
+                case MSG_CLOSE_SYSTEM_DIALOGS:
+                    if (DEBUG) Log.d(TAG, "onCloseSystemDialogs");
+                    onCloseSystemDialogs();
+                    break;
+                case MSG_DESTROY:
+                    if (DEBUG) Log.d(TAG, "doDestroy");
+                    doDestroy();
+                    break;
             }
         }
-    };
 
-    final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
+        @Override
+        public void onBackPressed() {
+            VoiceInteractionSession.this.onBackPressed();
+        }
+    }
+
+    final MyCallbacks mCallbacks = new MyCallbacks();
+
+    /**
+     * Information about where interesting parts of the input method UI appear.
+     */
+    public static final class Insets {
+        /**
+         * This is the top part of the UI that is the main content.  It is
+         * used to determine the basic space needed, to resize/pan the
+         * application behind.  It is assumed that this inset does not
+         * change very much, since any change will cause a full resize/pan
+         * of the application behind.  This value is relative to the top edge
+         * of the input method window.
+         */
+        public int contentTopInsets;
+
+        /**
+         * This is the region of the UI that is touchable.  It is used when
+         * {@link #touchableInsets} is set to {@link #TOUCHABLE_INSETS_REGION}.
+         * The region should be specified relative to the origin of the window frame.
+         */
+        public final Region touchableRegion = new Region();
+
+        /**
+         * Option for {@link #touchableInsets}: the entire window frame
+         * can be touched.
+         */
+        public static final int TOUCHABLE_INSETS_FRAME
+                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
+
+        /**
+         * Option for {@link #touchableInsets}: the area inside of
+         * the content insets can be touched.
+         */
+        public static final int TOUCHABLE_INSETS_CONTENT
+                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
+
+        /**
+         * Option for {@link #touchableInsets}: the region specified by
+         * {@link #touchableRegion} can be touched.
+         */
+        public static final int TOUCHABLE_INSETS_REGION
+                = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
+
+        /**
+         * Determine which area of the window is touchable by the user.  May
+         * be one of: {@link #TOUCHABLE_INSETS_FRAME},
+         * {@link #TOUCHABLE_INSETS_CONTENT}, or {@link #TOUCHABLE_INSETS_REGION}.
+         */
+        public int touchableInsets;
+    }
+
+    final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
+            new ViewTreeObserver.OnComputeInternalInsetsListener() {
+        public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
+            onComputeInsets(mTmpInsets);
+            info.contentInsets.top = info.visibleInsets.top = mTmpInsets.contentTopInsets;
+            info.touchableRegion.set(mTmpInsets.touchableRegion);
+            info.setTouchableInsets(mTmpInsets.touchableInsets);
+        }
+    };
 
     public VoiceInteractionSession(Context context) {
         this(context, new Handler());
@@ -169,7 +324,7 @@
     public VoiceInteractionSession(Context context, Handler handler) {
         mContext = context;
         mHandlerCaller = new HandlerCaller(context, handler.getLooper(),
-                mHandlerCallerCallback, true);
+                mCallbacks, true);
     }
 
     Request findRequest(IVoiceInteractorCallback callback, boolean newRequest) {
@@ -188,6 +343,192 @@
         }
     }
 
+    void doCreate(IVoiceInteractionManagerService service, IBinder token, Bundle args) {
+        mSystemService = service;
+        mToken = token;
+        onCreate(args);
+    }
+
+    void doDestroy() {
+        if (mInitialized) {
+            mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
+                    mInsetsComputer);
+            if (mWindowAdded) {
+                mWindow.dismiss();
+                mWindowAdded = false;
+            }
+            mInitialized = false;
+        }
+    }
+
+    void initViews() {
+        mInitialized = true;
+
+        mThemeAttrs = mContext.obtainStyledAttributes(android.R.styleable.VoiceInteractionSession);
+        mRootView = mInflater.inflate(
+                com.android.internal.R.layout.voice_interaction_session, null);
+        mRootView.setSystemUiVisibility(
+                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+        mWindow.setContentView(mRootView);
+        mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
+
+        mContentFrame = (FrameLayout)mRootView.findViewById(android.R.id.content);
+    }
+
+    public void showWindow() {
+        if (DEBUG) Log.v(TAG, "Showing window: mWindowAdded=" + mWindowAdded
+                + " mWindowVisible=" + mWindowVisible);
+
+        if (mInShowWindow) {
+            Log.w(TAG, "Re-entrance in to showWindow");
+            return;
+        }
+
+        try {
+            mInShowWindow = true;
+            if (!mWindowVisible) {
+                mWindowVisible = true;
+                if (!mWindowAdded) {
+                    mWindowAdded = true;
+                    View v = onCreateContentView();
+                    if (v != null) {
+                        setContentView(v);
+                    }
+                }
+                mWindow.show();
+            }
+        } finally {
+            mWindowWasVisible = true;
+            mInShowWindow = false;
+        }
+    }
+
+    public void hideWindow() {
+        if (mWindowVisible) {
+            mWindow.hide();
+            mWindowVisible = false;
+        }
+    }
+
+    /**
+     * You can call this to customize the theme used by your IME's window.
+     * This must be set before {@link #onCreate}, so you
+     * will typically call it in your constructor with the resource ID
+     * of your custom theme.
+     */
+    public void setTheme(int theme) {
+        if (mWindow != null) {
+            throw new IllegalStateException("Must be called before onCreate()");
+        }
+        mTheme = theme;
+    }
+
+    public void startVoiceActivity(Intent intent) {
+        if (mToken == null) {
+            throw new IllegalStateException("Can't call before onCreate()");
+        }
+        try {
+            int res = mSystemService.startVoiceActivity(mToken, intent,
+                    intent.resolveType(mContext.getContentResolver()));
+            Instrumentation.checkStartActivityResult(res, intent);
+        } catch (RemoteException e) {
+        }
+    }
+
+    public LayoutInflater getLayoutInflater() {
+        return mInflater;
+    }
+
+    public Dialog getWindow() {
+        return mWindow;
+    }
+
+    public void finish() {
+        if (mToken == null) {
+            throw new IllegalStateException("Can't call before onCreate()");
+        }
+        hideWindow();
+        try {
+            mSystemService.finish(mToken);
+        } catch (RemoteException e) {
+        }
+    }
+
+    public void onCreate(Bundle args) {
+        mTheme = mTheme != 0 ? mTheme
+                : com.android.internal.R.style.Theme_DeviceDefault_VoiceInteractionSession;
+        mInflater = (LayoutInflater)mContext.getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+        mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
+                mCallbacks, this, mDispatcherState, true);
+        mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        initViews();
+        mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
+        mWindow.setToken(mToken);
+    }
+
+    public void onDestroy() {
+    }
+
+    public View onCreateContentView() {
+        return null;
+    }
+
+    public void setContentView(View view) {
+        mContentFrame.removeAllViews();
+        mContentFrame.addView(view, new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+
+    }
+
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return false;
+    }
+
+    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+        return false;
+    }
+
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        return false;
+    }
+
+    public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
+        return false;
+    }
+
+    public void onBackPressed() {
+        finish();
+    }
+
+    public void onCloseSystemDialogs() {
+        finish();
+    }
+
+    /**
+     * Compute the interesting insets into your UI.  The default implementation
+     * uses the entire window frame as the insets.  The default touchable
+     * insets are {@link Insets#TOUCHABLE_INSETS_FRAME}.
+     *
+     * @param outInsets Fill in with the current UI insets.
+     */
+    public void onComputeInsets(Insets outInsets) {
+        int[] loc = mTmpLocation;
+        View decor = getWindow().getWindow().getDecorView();
+        decor.getLocationInWindow(loc);
+        outInsets.contentTopInsets = loc[1];
+        outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_FRAME;
+        outInsets.touchableRegion.setEmpty();
+    }
+
+    public void onTaskStarted(Intent intent, int taskId) {
+    }
+
+    public void onTaskFinished(Intent intent, int taskId) {
+        finish();
+    }
+
     public abstract boolean[] onGetSupportedCommands(Caller caller, String[] commands);
     public abstract void onConfirm(Caller caller, Request request, String prompt, Bundle extras);
     public abstract void onCommand(Caller caller, Request request, String command, Bundle extras);
diff --git a/core/java/android/service/voice/VoiceInteractionSessionService.java b/core/java/android/service/voice/VoiceInteractionSessionService.java
index 40e5bba..e793849 100644
--- a/core/java/android/service/voice/VoiceInteractionSessionService.java
+++ b/core/java/android/service/voice/VoiceInteractionSessionService.java
@@ -29,11 +29,15 @@
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 
+/**
+ * An active voice interaction session, initiated by a {@link VoiceInteractionService}.
+ */
 public abstract class VoiceInteractionSessionService extends Service {
 
     static final int MSG_NEW_SESSION = 1;
 
     IVoiceInteractionManagerService mSystemService;
+    VoiceInteractionSession mSession;
 
     IVoiceInteractionSessionService mInterface = new IVoiceInteractionSessionService.Stub() {
         public void newSession(IBinder token, Bundle args) {
@@ -73,9 +77,14 @@
     }
 
     void doNewSession(IBinder token, Bundle args) {
-        VoiceInteractionSession session = onNewSession(args);
+        if (mSession != null) {
+            mSession.doDestroy();
+            mSession = null;
+        }
+        mSession = onNewSession(args);
         try {
-            mSystemService.deliverNewSession(token, session.mSession, session.mInteractor);
+            mSystemService.deliverNewSession(token, mSession.mSession, mSession.mInteractor);
+            mSession.doCreate(mSystemService, token, args);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/transition/CircularPropagation.java b/core/java/android/transition/CircularPropagation.java
index 18a3d22..51beb51 100644
--- a/core/java/android/transition/CircularPropagation.java
+++ b/core/java/android/transition/CircularPropagation.java
@@ -34,7 +34,7 @@
 public class CircularPropagation extends VisibilityPropagation {
     private static final String TAG = "CircularPropagation";
 
-    private float mPropagationSpeed = 4.0f;
+    private float mPropagationSpeed = 3.0f;
 
     /**
      * Sets the speed at which transition propagation happens, relative to the duration of the
@@ -91,8 +91,12 @@
         float maxDistance = distance(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight());
         float distanceFraction = distance/maxDistance;
 
-        return Math.round(transition.getDuration() * directionMultiplier / mPropagationSpeed
-                * distanceFraction);
+        long duration = transition.getDuration();
+        if (duration < 0) {
+            duration = 300;
+        }
+
+        return Math.round(duration * directionMultiplier / mPropagationSpeed * distanceFraction);
     }
 
     private static float distance(float x1, float y1, float x2, float y2) {
diff --git a/core/java/android/transition/SidePropagation.java b/core/java/android/transition/SidePropagation.java
index c331945..5d38ac8 100644
--- a/core/java/android/transition/SidePropagation.java
+++ b/core/java/android/transition/SidePropagation.java
@@ -52,7 +52,7 @@
      */
     public static final int BOTTOM = Slide.BOTTOM;
 
-    private float mPropagationSpeed = 4.0f;
+    private float mPropagationSpeed = 3.0f;
     private int mSide = BOTTOM;
 
     /**
@@ -129,8 +129,12 @@
         float maxDistance = getMaxDistance(sceneRoot);
         float distanceFraction = distance/maxDistance;
 
-        return Math.round(transition.getDuration() * directionMultiplier / mPropagationSpeed
-                * distanceFraction);
+        long duration = transition.getDuration();
+        if (duration < 0) {
+            duration = 300;
+        }
+
+        return Math.round(duration * directionMultiplier / mPropagationSpeed * distanceFraction);
     }
 
     private int distance(int viewX, int viewY, int epicenterX, int epicenterY,
diff --git a/core/java/android/util/Range.java b/core/java/android/util/Range.java
new file mode 100644
index 0000000..9a4bd4b
--- /dev/null
+++ b/core/java/android/util/Range.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import static com.android.internal.util.Preconditions.*;
+
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+/**
+ * Immutable class for describing the range of two numeric values.
+ * <p>
+ * A range (or "interval") defines the inclusive boundaries around a contiguous span of
+ * values of some {@link Comparable} type; for example,
+ * "integers from 1 to 100 inclusive."
+ * </p>
+ * <p>
+ * All ranges are bounded, and the left side of the range is always {@code >=}
+ * the right side of the range.
+ * </p>
+ *
+ * <p>Although the implementation itself is immutable, there is no restriction that objects
+ * stored must also be immutable. If mutable objects are stored here, then the range
+ * effectively becomes mutable. </p>
+ */
+public final class Range<T extends Comparable<? super T>> {
+    /**
+     * Create a new immutable range.
+     *
+     * <p>
+     * The endpoints are {@code [lower, upper]}; that
+     * is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal}
+     * to {@code upper}.
+     * </p>
+     *
+     * @param lower The lower endpoint (inclusive)
+     * @param upper The upper endpoint (inclusive)
+     *
+     * @throws NullPointerException if {@code lower} or {@code upper} is {@code null}
+     */
+    public Range(final T lower, final T upper) {
+        mLower = checkNotNull(lower, "lower must not be null");
+        mUpper = checkNotNull(upper, "upper must not be null");
+
+        if (lower.compareTo(upper) > 0) {
+            throw new IllegalArgumentException("lower must be less than or equal to upper");
+        }
+    }
+
+    /**
+     * Create a new immutable range, with the argument types inferred.
+     *
+     * <p>
+     * The endpoints are {@code [lower, upper]}; that
+     * is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal}
+     * to {@code upper}.
+     * </p>
+     *
+     * @param lower The lower endpoint (inclusive)
+     * @param upper The upper endpoint (inclusive)
+     *
+     * @throws NullPointerException if {@code lower} or {@code upper} is {@code null}
+     */
+    public static <T extends Comparable<? super T>> Range<T> create(final T lower, final T upper) {
+        return new Range<T>(lower, upper);
+    }
+
+    /**
+     * Get the lower endpoint.
+     *
+     * @return a non-{@code null} {@code T} reference
+     */
+    public T getLower() {
+        return mLower;
+    }
+
+    /**
+     * Get the upper endpoint.
+     *
+     * @return a non-{@code null} {@code T} reference
+     */
+    public T getUpper() {
+        return mUpper;
+    }
+
+    /**
+     * Compare two ranges for equality.
+     *
+     * <p>A range is considered equal if and only if both the lower and upper endpoints
+     * are also equal.</p>
+     *
+     * @return {@code true} if the ranges are equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof Range) {
+            @SuppressWarnings("rawtypes")
+            final
+            Range other = (Range) obj;
+            return mLower.equals(other.mLower) && mUpper.equals(other.mUpper);
+        }
+        return false;
+    }
+
+    /**
+     * Return the range as a string representation {@code "[lower, upper]"}.
+     *
+     * @return string representation of the range
+     */
+    @Override
+    public String toString() {
+        return String.format("[%s, %s]", mLower, mUpper);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return HashCodeHelpers.hashCode(mLower, mUpper);
+    }
+
+    private final T mLower;
+    private final T mUpper;
+};
diff --git a/core/java/android/util/Size.java b/core/java/android/util/Size.java
new file mode 100644
index 0000000..ba1a35f
--- /dev/null
+++ b/core/java/android/util/Size.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+/**
+ * Immutable class for describing width and height dimensions in pixels.
+ */
+public final class Size {
+    /**
+     * Create a new immutable Size instance.
+     *
+     * @param width The width of the size, in pixels
+     * @param height The height of the size, in pixels
+     */
+    public Size(int width, int height) {
+        mWidth = width;
+        mHeight = height;
+    }
+
+    /**
+     * Get the width of the size (in pixels).
+     * @return width
+     */
+    public int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * Get the height of the size (in pixels).
+     * @return height
+     */
+    public int getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * Check if this size is equal to another size.
+     * <p>
+     * Two sizes are equal if and only if both their widths and heights are
+     * equal.
+     * </p>
+     * <p>
+     * A size object is never equal to any other type of object.
+     * </p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof Size) {
+            Size other = (Size) obj;
+            return mWidth == other.mWidth && mHeight == other.mHeight;
+        }
+        return false;
+    }
+
+    /**
+     * Return the size represented as a string with the format {@code "WxH"}
+     *
+     * @return string representation of the size
+     */
+    @Override
+    public String toString() {
+        return mWidth + "x" + mHeight;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        // assuming most sizes are <2^16, doing a rotate will give us perfect hashing
+        return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
+    }
+
+    private final int mWidth;
+    private final int mHeight;
+};
diff --git a/core/java/android/util/SizeF.java b/core/java/android/util/SizeF.java
new file mode 100644
index 0000000..0a8b4ed
--- /dev/null
+++ b/core/java/android/util/SizeF.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Immutable class for describing width and height dimensions in some arbitrary
+ * unit.
+ * <p>
+ * Width and height are finite values stored as a floating point representation.
+ * </p>
+ */
+public final class SizeF {
+    /**
+     * Create a new immutable SizeF instance.
+     *
+     * <p>Both the {@code width} and the {@code height} must be a finite number.
+     * In particular, {@code NaN} and positive/negative infinity are illegal values.</p>
+     *
+     * @param width The width of the size
+     * @param height The height of the size
+     *
+     * @throws IllegalArgumentException
+     *             if either {@code width} or {@code height} was not finite.
+     */
+    public SizeF(final float width, final float height) {
+        mWidth = checkArgumentFinite(width, "width");
+        mHeight = checkArgumentFinite(height, "height");
+    }
+
+    /**
+     * Get the width of the size (as an arbitrary unit).
+     * @return width
+     */
+    public float getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * Get the height of the size (as an arbitrary unit).
+     * @return height
+     */
+    public float getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * Check if this size is equal to another size.
+     *
+     * <p>Two sizes are equal if and only if both their widths and heights are the same.</p>
+     *
+     * <p>For this purpose, the width/height float values are considered to be the same if and only
+     * if the method {@link Float#floatToIntBits(float)} returns the identical {@code int} value
+     * when applied to each.</p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof SizeF) {
+            final SizeF other = (SizeF) obj;
+            return mWidth == other.mWidth && mHeight == other.mHeight;
+        }
+        return false;
+    }
+
+    /**
+     * Return the size represented as a string with the format {@code "WxH"}
+     *
+     * @return string representation of the size
+     */
+    @Override
+    public String toString() {
+        return mWidth + "x" + mHeight;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return Float.floatToIntBits(mWidth) ^ Float.floatToIntBits(mHeight);
+    }
+
+    private final float mWidth;
+    private final float mHeight;
+};
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index 0afbde9..ba1c4b6 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -96,7 +96,7 @@
             return mTheme;
         }
 
-        mThemeResource = Resources.selectDefaultTheme(mThemeResource,
+        mThemeResource = getResources().selectDefaultTheme(mThemeResource,
                 getApplicationInfo().targetSdkVersion);
         initializeTheme();
 
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 34b85d9..11948b2 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
 import android.graphics.DrawFilter;
 import android.graphics.Matrix;
 import android.graphics.NinePatch;
@@ -889,6 +890,16 @@
             float radius, long paint);
 
     @Override
+    public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
+            CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
+        nDrawCircle(mRenderer, cx.getNativeContainer(), cy.getNativeContainer(),
+                radius.getNativeContainer(), paint.getNativeContainer());
+    }
+
+    private static native void nDrawCircle(long renderer, long propCx,
+            long propCy, long propRadius, long propPaint);
+
+    @Override
     public void drawColor(int color) {
         drawColor(color, PorterDuff.Mode.SRC_OVER);
     }
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index 2b29e5c..a94ec3a 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.util.Pools.SynchronizedPool;
 
 /**
@@ -32,19 +33,25 @@
     private static final SynchronizedPool<GLES20RecordingCanvas> sPool =
             new SynchronizedPool<GLES20RecordingCanvas>(POOL_LIMIT);
 
+    RenderNode mNode;
+
     private GLES20RecordingCanvas() {
         super(true, true);
     }
 
-    static GLES20RecordingCanvas obtain() {
+    static GLES20RecordingCanvas obtain(@NonNull RenderNode node) {
+        if (node == null) throw new IllegalArgumentException("node cannot be null");
+
         GLES20RecordingCanvas canvas = sPool.acquire();
         if (canvas == null) {
             canvas = new GLES20RecordingCanvas();
         }
+        canvas.mNode = node;
         return canvas;
     }
 
     void recycle() {
+        mNode = null;
         sPool.release(this);
     }
 
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 233f846..7ec2cc6 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
 import android.graphics.Paint;
 import android.graphics.Rect;
 
@@ -189,4 +190,7 @@
      * @hide
      */
     abstract void clearLayerUpdates();
+
+    public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
+            CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
 }
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index e19bda9..b9ed801 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -21,13 +21,16 @@
 import android.os.Message;
 import android.os.Trace;
 import android.widget.FrameLayout;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.Xml;
 
 import java.io.IOException;
@@ -61,7 +64,8 @@
  * @see Context#getSystemService
  */
 public abstract class LayoutInflater {
-    private final boolean DEBUG = false;
+    private static final String TAG = LayoutInflater.class.getSimpleName();
+    private static final boolean DEBUG = false;
 
     /**
      * This field should be made private, so it is hidden from the SDK.
@@ -395,8 +399,13 @@
      *         the inflated XML file.
      */
     public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
-        if (DEBUG) System.out.println("INFLATING from resource: " + resource);
-        XmlResourceParser parser = getContext().getResources().getLayout(resource);
+        final Resources res = getContext().getResources();
+        if (DEBUG) {
+            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
+                    + Integer.toHexString(resource) + ")");
+        }
+
+        final XmlResourceParser parser = res.getLayout(resource);
         try {
             return inflate(parser, root, attachToRoot);
         } finally {
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 8b80c3e0..0cfde94 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -239,7 +239,7 @@
      * @see #isValid()
      */
     public HardwareCanvas start(int width, int height) {
-        HardwareCanvas canvas = GLES20RecordingCanvas.obtain();
+        HardwareCanvas canvas = GLES20RecordingCanvas.obtain(this);
         canvas.setViewport(width, height);
         // The dirty rect should always be null for a display list
         canvas.onPreDraw(null);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index b70ae3d..a675821 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -16,6 +16,9 @@
 
 package android.view;
 
+import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
 import android.util.SparseIntArray;
 
 import java.lang.ref.WeakReference;
@@ -26,18 +29,22 @@
 public final class RenderNodeAnimator {
 
     // Keep in sync with enum RenderProperty in Animator.h
-    private static final int TRANSLATION_X = 0;
-    private static final int TRANSLATION_Y = 1;
-    private static final int TRANSLATION_Z = 2;
-    private static final int SCALE_X = 3;
-    private static final int SCALE_Y = 4;
-    private static final int ROTATION = 5;
-    private static final int ROTATION_X = 6;
-    private static final int ROTATION_Y = 7;
-    private static final int X = 8;
-    private static final int Y = 9;
-    private static final int Z = 10;
-    private static final int ALPHA = 11;
+    public static final int TRANSLATION_X = 0;
+    public static final int TRANSLATION_Y = 1;
+    public static final int TRANSLATION_Z = 2;
+    public static final int SCALE_X = 3;
+    public static final int SCALE_Y = 4;
+    public static final int ROTATION = 5;
+    public static final int ROTATION_X = 6;
+    public static final int ROTATION_Y = 7;
+    public static final int X = 8;
+    public static final int Y = 9;
+    public static final int Z = 10;
+    public static final int ALPHA = 11;
+
+    // Keep in sync with enum PaintFields in Animator.h
+    public static final int PAINT_STROKE_WIDTH = 0;
+    public static final int PAINT_ALPHA = 1;
 
     // ViewPropertyAnimator uses a mask for its values, we need to remap them
     // to the enum values here. RenderPropertyAnimator can't use the mask values
@@ -59,8 +66,8 @@
     }};
 
     // Keep in sync DeltaValueType in Animator.h
-    private static final int DELTA_TYPE_ABSOLUTE = 0;
-    private static final int DELTA_TYPE_DELTA = 1;
+    public static final int DELTA_TYPE_ABSOLUTE = 0;
+    public static final int DELTA_TYPE_DELTA = 1;
 
     private RenderNode mTarget;
     private long mNativePtr;
@@ -74,6 +81,19 @@
                 property, deltaType, deltaValue);
     }
 
+    public RenderNodeAnimator(CanvasProperty<Float> property, int deltaType, float deltaValue) {
+        mNativePtr = nCreateCanvasPropertyFloatAnimator(
+                new WeakReference<RenderNodeAnimator>(this),
+                property.getNativeContainer(), deltaType, deltaValue);
+    }
+
+    public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField,
+            int deltaType, float deltaValue) {
+        mNativePtr = nCreateCanvasPropertyPaintAnimator(
+                new WeakReference<RenderNodeAnimator>(this),
+                property.getNativeContainer(), paintField, deltaType, deltaValue);
+    }
+
     public void start(View target) {
         mTarget = target.mRenderNode;
         mTarget.addAnimator(this);
@@ -81,6 +101,15 @@
         target.invalidateViewProperty(true, false);
     }
 
+    public void start(Canvas canvas) {
+        if (!(canvas instanceof GLES20RecordingCanvas)) {
+            throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
+        }
+        GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
+        mTarget = recordingCanvas.mNode;
+        mTarget.addAnimator(this);
+    }
+
     public void cancel() {
         mTarget.removeAnimator(this);
     }
@@ -117,6 +146,10 @@
 
     private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
             int property, int deltaValueType, float deltaValue);
+    private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
+            long canvasProperty, int deltaValueType, float deltaValue);
+    private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
+            long canvasProperty, int paintField, int deltaValueType, float deltaValue);
     private static native void nSetDuration(long nativePtr, int duration);
     private static native void nUnref(long nativePtr);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 85e3b3d..6afff4d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17989,7 +17989,9 @@
      *
      * <p>If this property is set to true the view will be permitted to initiate nested
      * scrolling operations with a compatible parent view in the current hierarchy. If this
-     * view does not implement nested scrolling this will have no effect.</p>
+     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
+     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
+     * the nested scroll.</p>
      *
      * @param enabled true to enable nested scrolling, false to disable
      *
@@ -17999,6 +18001,7 @@
         if (enabled) {
             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
         } else {
+            stopNestedScroll();
             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
         }
     }
@@ -18138,23 +18141,29 @@
     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
             int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
-            int startX = 0;
-            int startY = 0;
-            if (offsetInWindow != null) {
-                getLocationInWindow(offsetInWindow);
-                startX = offsetInWindow[0];
-                startY = offsetInWindow[1];
-            }
+            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
+                int startX = 0;
+                int startY = 0;
+                if (offsetInWindow != null) {
+                    getLocationInWindow(offsetInWindow);
+                    startX = offsetInWindow[0];
+                    startY = offsetInWindow[1];
+                }
 
-            mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
-                    dxUnconsumed, dyUnconsumed);
+                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
+                        dxUnconsumed, dyUnconsumed);
 
-            if (offsetInWindow != null) {
-                getLocationInWindow(offsetInWindow);
-                offsetInWindow[0] -= startX;
-                offsetInWindow[1] -= startY;
+                if (offsetInWindow != null) {
+                    getLocationInWindow(offsetInWindow);
+                    offsetInWindow[0] -= startX;
+                    offsetInWindow[1] -= startY;
+                }
+                return true;
+            } else if (offsetInWindow != null) {
+                // No motion, no dispatch. Keep offsetInWindow up to date.
+                offsetInWindow[0] = 0;
+                offsetInWindow[1] = 0;
             }
-            return true;
         }
         return false;
     }
@@ -18180,30 +18189,35 @@
      */
     public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
-            int startX = 0;
-            int startY = 0;
-            if (offsetInWindow != null) {
-                getLocationInWindow(offsetInWindow);
-                startX = offsetInWindow[0];
-                startY = offsetInWindow[1];
-            }
-
-            if (consumed == null) {
-                if (mTempNestedScrollConsumed == null) {
-                    mTempNestedScrollConsumed = new int[2];
+            if (dx != 0 || dy != 0) {
+                int startX = 0;
+                int startY = 0;
+                if (offsetInWindow != null) {
+                    getLocationInWindow(offsetInWindow);
+                    startX = offsetInWindow[0];
+                    startY = offsetInWindow[1];
                 }
-                consumed = mTempNestedScrollConsumed;
-            }
-            consumed[0] = 0;
-            consumed[1] = 0;
-            mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
 
-            if (offsetInWindow != null) {
-                getLocationInWindow(offsetInWindow);
-                offsetInWindow[0] -= startX;
-                offsetInWindow[1] -= startY;
+                if (consumed == null) {
+                    if (mTempNestedScrollConsumed == null) {
+                        mTempNestedScrollConsumed = new int[2];
+                    }
+                    consumed = mTempNestedScrollConsumed;
+                }
+                consumed[0] = 0;
+                consumed[1] = 0;
+                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
+
+                if (offsetInWindow != null) {
+                    getLocationInWindow(offsetInWindow);
+                    offsetInWindow[0] -= startX;
+                    offsetInWindow[1] -= startY;
+                }
+                return consumed[0] != 0 || consumed[1] != 0;
+            } else if (offsetInWindow != null) {
+                offsetInWindow[0] = 0;
+                offsetInWindow[1] = 0;
             }
-            return consumed[0] != 0 || consumed[1] != 0;
         }
         return false;
     }
@@ -18211,18 +18225,24 @@
     /**
      * Dispatch a fling to a nested scrolling parent.
      *
-     * <p>If a nested scrolling child view would normally fling but it is at the edge of its
-     * own content it should use this method to delegate the fling to its nested scrolling parent.
-     * The view implementation can use a {@link VelocityTracker} to obtain the velocity values
-     * to pass.</p>
+     * <p>This method should be used to indicate that a nested scrolling child has detected
+     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
+     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
+     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
+     * along a scrollable axis.</p>
+     *
+     * <p>If a nested scrolling child view would normally fling but it is at the edge of
+     * its own content, it can use this method to delegate the fling to its nested scrolling
+     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
      *
      * @param velocityX Horizontal fling velocity in pixels per second
      * @param velocityY Vertical fling velocity in pixels per second
-     * @return true if the nested scrolling parent consumed the fling
+     * @param consumed true if the child consumed the fling, false otherwise
+     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
      */
-    public boolean dispatchNestedFling(float velocityX, float velocityY) {
+    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
-            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY);
+            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
         }
         return false;
     }
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 5112b9a..20ef429 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -234,6 +234,7 @@
     private final int mOverscrollDistance;
     private final int mOverflingDistance;
     private final boolean mFadingMarqueeEnabled;
+    private final long mGlobalActionsKeyTimeout;
 
     private boolean sHasPermanentMenuKey;
     private boolean sHasPermanentMenuKeySet;
@@ -261,6 +262,7 @@
         mOverscrollDistance = OVERSCROLL_DISTANCE;
         mOverflingDistance = OVERFLING_DISTANCE;
         mFadingMarqueeEnabled = true;
+        mGlobalActionsKeyTimeout = GLOBAL_ACTIONS_KEY_TIMEOUT;
     }
 
     /**
@@ -287,8 +289,6 @@
 
         mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f);
         mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f);
-        mMinimumFlingVelocity = (int) (density * MINIMUM_FLING_VELOCITY + 0.5f);
-        mMaximumFlingVelocity = (int) (density * MAXIMUM_FLING_VELOCITY + 0.5f);
         mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f);
         mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);
         mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
@@ -339,6 +339,13 @@
         mPagingTouchSlop = mTouchSlop * 2;
 
         mDoubleTapTouchSlop = mTouchSlop;
+
+        mMinimumFlingVelocity = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.config_viewMinFlingVelocity);
+        mMaximumFlingVelocity = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.config_viewMaxFlingVelocity);
+        mGlobalActionsKeyTimeout = res.getInteger(
+                com.android.internal.R.integer.config_globalActionsKeyTimeout);
     }
 
     /**
@@ -695,12 +702,24 @@
      *
      * @return how long a user needs to press the relevant key to bring up
      *   the global actions dialog.
+     * @deprecated use getDeviceGlobalActionKeyTimeout
      */
     public static long getGlobalActionKeyTimeout() {
         return GLOBAL_ACTIONS_KEY_TIMEOUT;
     }
 
     /**
+     * The amount of time a user needs to press the relevant key to bring up
+     * the global actions dialog.
+     *
+     * @return how long a user needs to press the relevant key to bring up
+     *   the global actions dialog.
+     */
+    public long getDeviceGlobalActionKeyTimeout() {
+        return mGlobalActionsKeyTimeout;
+    }
+
+    /**
      * The amount of friction applied to scrolls and flings.
      *
      * @return A scalar dimensionless value representing the coefficient of
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 8865ab4..43bc0b6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2342,7 +2342,6 @@
 
         if (disallowIntercept) {
             mGroupFlags |= FLAG_DISALLOW_INTERCEPT;
-            stopNestedScroll();
         } else {
             mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
         }
@@ -5914,7 +5913,7 @@
      * @inheritDoc
      */
     @Override
-    public boolean onNestedFling(View target, float velocityX, float velocityY) {
+    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
         return false;
     }
 
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 3cd6449..588b9cd 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -512,14 +512,21 @@
     /**
      * Request a fling from a nested scroll.
      *
+     * <p>This method signifies that a nested scrolling child has detected suitable conditions
+     * for a fling. Generally this means that a touch scroll has ended with a
+     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
+     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
+     * along a scrollable axis.</p>
+     *
      * <p>If a nested scrolling child view would normally fling but it is at the edge of
-     * its own content, it can delegate the fling to its nested scrolling parent instead.
-     * This method allows the parent to optionally consume the fling.</p>
+     * its own content, it can use this method to delegate the fling to its nested scrolling
+     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
      *
      * @param target View that initiated the nested scroll
      * @param velocityX Horizontal velocity in pixels per second.
      * @param velocityY Vertical velocity in pixels per second
-     * @return true if this parent consumed the fling
+     * @param consumed true if the child consumed the fling, false otherwise
+     * @return true if this parent consumed or otherwise reacted to the fling
      */
-    public boolean onNestedFling(View target, float velocityX, float velocityY);
+    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed);
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 14e422c..db87394 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -234,6 +234,7 @@
 
     InputStage mFirstInputStage;
     InputStage mFirstPostImeInputStage;
+    InputStage mSyntheticInputStage;
 
     boolean mWindowAttributesChanged = false;
     int mWindowAttributesChangesFlag = 0;
@@ -599,8 +600,8 @@
 
                 // Set up the input pipeline.
                 CharSequence counterSuffix = attrs.getTitle();
-                InputStage syntheticInputStage = new SyntheticInputStage();
-                InputStage viewPostImeStage = new ViewPostImeInputStage(syntheticInputStage);
+                mSyntheticInputStage = new SyntheticInputStage();
+                InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
                 InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
                         "aq:native-post-ime:" + counterSuffix);
                 InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
@@ -2587,10 +2588,6 @@
      * @param canvas The canvas on which to draw.
      */
     private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) {
-        if (!mAttachInfo.mHasWindowFocus) {
-            return;
-        }
-
         final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext);
         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
             return;
@@ -3007,6 +3004,7 @@
     private final static int MSG_INVALIDATE_WORLD = 23;
     private final static int MSG_WINDOW_MOVED = 24;
     private final static int MSG_FLUSH_LAYER_UPDATES = 25;
+    private final static int MSG_SYNTHESIZE_INPUT_EVENT = 26;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -3056,6 +3054,8 @@
                     return "MSG_WINDOW_MOVED";
                 case MSG_FLUSH_LAYER_UPDATES:
                     return "MSG_FLUSH_LAYER_UPDATES";
+                case MSG_SYNTHESIZE_INPUT_EVENT:
+                    return "MSG_SYNTHESIZE_INPUT_EVENT";
             }
             return super.getMessageName(message);
         }
@@ -3218,6 +3218,10 @@
                 enqueueInputEvent(event, receiver, 0, true);
                 args.recycle();
             } break;
+            case MSG_SYNTHESIZE_INPUT_EVENT: {
+                InputEvent event = (InputEvent)msg.obj;
+                enqueueInputEvent(event, null, QueuedInputEvent.FLAG_UNHANDLED, true);
+            } break;
             case MSG_DISPATCH_KEY_FROM_IME: {
                 if (LOCAL_LOGV) Log.v(
                     TAG, "Dispatching key "
@@ -3227,7 +3231,8 @@
                     // The IME is trying to say this event is from the
                     // system!  Bad bad bad!
                     //noinspection UnusedAssignment
-                    event = KeyEvent.changeFlags(event, event.getFlags() & ~KeyEvent.FLAG_FROM_SYSTEM);
+                    event = KeyEvent.changeFlags(event, event.getFlags() &
+                            ~KeyEvent.FLAG_FROM_SYSTEM);
                 }
                 enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
             } break;
@@ -4023,6 +4028,7 @@
         private final SyntheticJoystickHandler mJoystick = new SyntheticJoystickHandler();
         private final SyntheticTouchNavigationHandler mTouchNavigation =
                 new SyntheticTouchNavigationHandler();
+        private final SyntheticKeyboardHandler mKeyboard = new SyntheticKeyboardHandler();
 
         public SyntheticInputStage() {
             super(null);
@@ -4045,7 +4051,11 @@
                     mTouchNavigation.process(event);
                     return FINISH_HANDLED;
                 }
+            } else if ((q.mFlags & QueuedInputEvent.FLAG_UNHANDLED) != 0) {
+                mKeyboard.process((KeyEvent)q.mEvent);
+                return FINISH_HANDLED;
             }
+
             return FORWARD;
         }
 
@@ -4882,6 +4892,33 @@
         };
     }
 
+    final class SyntheticKeyboardHandler {
+        public void process(KeyEvent event) {
+            if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
+                return;
+            }
+
+            final KeyCharacterMap kcm = event.getKeyCharacterMap();
+            final int keyCode = event.getKeyCode();
+            final int metaState = event.getMetaState();
+
+            // Check for fallback actions specified by the key character map.
+            KeyCharacterMap.FallbackAction fallbackAction =
+                    kcm.getFallbackAction(keyCode, metaState);
+            if (fallbackAction != null) {
+                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
+                KeyEvent fallbackEvent = KeyEvent.obtain(
+                        event.getDownTime(), event.getEventTime(),
+                        event.getAction(), fallbackAction.keyCode,
+                        event.getRepeatCount(), fallbackAction.metaState,
+                        event.getDeviceId(), event.getScanCode(),
+                        flags, event.getSource(), null);
+                fallbackAction.recycle();
+                enqueueInputEvent(fallbackEvent);
+            }
+        }
+    }
+
     /**
      * Returns true if the key is used for keyboard navigation.
      * @param keyEvent The key event.
@@ -5461,6 +5498,7 @@
         public static final int FLAG_FINISHED = 1 << 2;
         public static final int FLAG_FINISHED_HANDLED = 1 << 3;
         public static final int FLAG_RESYNTHESIZED = 1 << 4;
+        public static final int FLAG_UNHANDLED = 1 << 5;
 
         public QueuedInputEvent mNext;
 
@@ -5475,6 +5513,14 @@
             return mEvent instanceof MotionEvent
                     && mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER);
         }
+
+        public boolean shouldSendToSynthesizer() {
+            if ((mFlags & FLAG_UNHANDLED) != 0) {
+                return true;
+            }
+
+            return false;
+        }
     }
 
     private QueuedInputEvent obtainQueuedInputEvent(InputEvent event,
@@ -5578,7 +5624,13 @@
             mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
         }
 
-        InputStage stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
+        InputStage stage;
+        if (q.shouldSendToSynthesizer()) {
+            stage = mSyntheticInputStage;
+        } else {
+            stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
+        }
+
         if (stage != null) {
             stage.deliver(q);
         } else {
@@ -5810,43 +5862,29 @@
         mHandler.sendMessage(msg);
     }
 
+    public void synthesizeInputEvent(InputEvent event) {
+        Message msg = mHandler.obtainMessage(MSG_SYNTHESIZE_INPUT_EVENT, event);
+        msg.setAsynchronous(true);
+        mHandler.sendMessage(msg);
+    }
+
     public void dispatchKeyFromIme(KeyEvent event) {
         Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY_FROM_IME, event);
         msg.setAsynchronous(true);
         mHandler.sendMessage(msg);
     }
 
-    public void dispatchUnhandledKey(KeyEvent event) {
-        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
-            // Some fallback keys are decided by the ViewRoot as they might have special
-            // properties (e.g. are locale aware). These take precedence over fallbacks defined by
-            // the kcm.
-            final KeyCharacterMap kcm = event.getKeyCharacterMap();
-            final int keyCode = event.getKeyCode();
-            final int metaState = event.getMetaState();
-
-            // Check for fallback actions specified by the key character map.
-            KeyCharacterMap.FallbackAction fallbackAction =
-                    kcm.getFallbackAction(keyCode, metaState);
-            if (fallbackAction != null) {
-                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
-                KeyEvent fallbackEvent = KeyEvent.obtain(
-                        event.getDownTime(), event.getEventTime(),
-                        event.getAction(), fallbackAction.keyCode,
-                        event.getRepeatCount(), fallbackAction.metaState,
-                        event.getDeviceId(), event.getScanCode(),
-                        flags, event.getSource(), null);
-                fallbackAction.recycle();
-                dispatchInputEvent(fallbackEvent);
-            }
-        }
-    }
-
+    /**
+     * Reinject unhandled {@link InputEvent}s in order to synthesize fallbacks events.
+     *
+     * Note that it is the responsibility of the caller of this API to recycle the InputEvent it
+     * passes in.
+     */
     public void dispatchUnhandledInputEvent(InputEvent event) {
-        if (event instanceof KeyEvent) {
-            dispatchUnhandledKey((KeyEvent) event);
-            return;
+        if (event instanceof MotionEvent) {
+            event = MotionEvent.obtain((MotionEvent) event);
         }
+        synthesizeInputEvent(event);
     }
 
     public void dispatchAppVisibility(boolean visible) {
@@ -6131,7 +6169,7 @@
     }
 
     @Override
-    public boolean onNestedFling(View target, float velocityX, float velocityY) {
+    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
         return false;
     }
 
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index c524611..4fde1e4 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -443,8 +443,6 @@
     public final int OFF_BECAUSE_OF_USER = 2;
     /** Screen turned off because of timeout */
     public final int OFF_BECAUSE_OF_TIMEOUT = 3;
-    /** Screen turned off because of proximity sensor */
-    public final int OFF_BECAUSE_OF_PROX_SENSOR = 4;
 
     /** @hide */
     @IntDef({USER_ROTATION_FREE, USER_ROTATION_LOCKED})
@@ -900,23 +898,23 @@
     public int focusChangedLw(WindowState lastFocus, WindowState newFocus);
     
     /**
-     * Called after the screen turns off.
+     * Called when the device is going to sleep.
      *
      * @param why {@link #OFF_BECAUSE_OF_USER} or
      * {@link #OFF_BECAUSE_OF_TIMEOUT}.
      */
-    public void screenTurnedOff(int why);
+    public void goingToSleep(int why);
 
     public interface ScreenOnListener {
         void onScreenOn();
     }
 
     /**
-     * Called when the power manager would like to turn the screen on.
+     * Called when the device is waking up.
      * Must call back on the listener to tell it when the higher-level system
      * is ready for the screen to go on (i.e. the lock screen is shown).
      */
-    public void screenTurningOn(ScreenOnListener screenOnListener);
+    public void wakingUp(ScreenOnListener screenOnListener);
 
     /**
      * Return whether the screen is about to turn on or is currently on.
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index f8160c8..bc2d7ec 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -259,7 +259,7 @@
     public InputMethodInfo(String packageName, String className,
             CharSequence label, String settingsActivity) {
         this(buildDummyResolveInfo(packageName, className, label), false, settingsActivity, null,
-                0, false);
+                0, false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */);
     }
 
     /**
@@ -269,6 +269,17 @@
     public InputMethodInfo(ResolveInfo ri, boolean isAuxIme,
             String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
             boolean forceDefault) {
+        this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId,
+                forceDefault, true /* supportsSwitchingToNextInputMethod */);
+    }
+
+    /**
+     * Temporary API for creating a built-in input method for test.
+     * @hide
+     */
+    public InputMethodInfo(ResolveInfo ri, boolean isAuxIme,
+            String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
+            boolean forceDefault, boolean supportsSwitchingToNextInputMethod) {
         final ServiceInfo si = ri.serviceInfo;
         mService = ri;
         mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -277,7 +288,7 @@
         mIsAuxIme = isAuxIme;
         mSubtypes = new InputMethodSubtypeArray(subtypes);
         mForceDefault = forceDefault;
-        mSupportsSwitchingToNextInputMethod = true;
+        mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
     }
 
     private static ResolveInfo buildDummyResolveInfo(String packageName, String className,
diff --git a/core/java/android/webkit/ClientCertRequest.java b/core/java/android/webkit/ClientCertRequest.java
index 8951786..588b868 100644
--- a/core/java/android/webkit/ClientCertRequest.java
+++ b/core/java/android/webkit/ClientCertRequest.java
@@ -36,8 +36,6 @@
  * host/port pair. The user can clear the cached data using
  * {@link WebView#clearClientCertPreferences}.
  *
- * TODO(sgurun) unhide
- * @hide
  */
 public interface ClientCertRequest {
     /**
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 98ef66e..7c32c5b 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -171,6 +171,38 @@
     }
 
     /**
+     * Used with {@link #setMixedContentMode}
+     *
+     * In this mode, the WebView will allow a secure origin to load content from any other origin,
+     * even if that origin is insecure. This is the least secure mode of operation for the WebView,
+     * and where possible apps should not set this mode.
+     */
+    public static final int MIXED_CONTENT_ALWAYS_ALLOW = 0;
+
+    /**
+     * Used with {@link #setMixedContentMode}
+     *
+     * In this mode, the WebView will not allow a secure origin to load content from an insecure
+     * origin. This is the preferred and most secure mode of operation for the WebView and apps are
+     * strongly advised to use this mode.
+     */
+    public static final int MIXED_CONTENT_NEVER_ALLOW = 1;
+
+    /**
+     * Used with {@link #setMixedContentMode}
+     *
+     * In this mode, the WebView will attempt to be compatible with the approach of a modern web
+     * browser with regard to mixed content. Some insecure content may be allowed to be loaded by
+     * a secure origin and other types of content will be blocked. The types of content are allowed
+     * or blocked may change release to release and are not explicitly defined.
+     *
+     * This mode is intended to be used by apps that are not in control of the content that they
+     * render but desire to operate in a reasonably secure environment. For highest security, apps
+     * are recommended to use {@link #MIXED_CONTENT_NEVER_ALLOW}.
+     */
+    public static final int MIXED_CONTENT_COMPATIBILITY_MODE = 2;
+
+    /**
      * Hidden constructor to prevent clients from creating a new settings
      * instance or deriving the class.
      *
@@ -1403,4 +1435,29 @@
     public int getCacheMode() {
         throw new MustOverrideException();
     }
+
+    /**
+     * Configures the WebView's behavior when a secure origin attempts to load a resource from an
+     * insecure origin.
+     *
+     * By default, apps that target {@link android.os.Build.VERSION_CODES#KITKAT} or below default
+     * to {@link #MIXED_CONTENT_ALWAYS_ALLOW}. Apps targeting
+     * {@link android.os.Build.VERSION_CODES#L} default to {@link #MIXED_CONTENT_NEVER_ALLOW}.
+     *
+     * The preferred and most secure mode of operation for the WebView is
+     * {@link #MIXED_CONTENT_NEVER_ALLOW} and use of {@link #MIXED_CONTENT_ALWAYS_ALLOW} is
+     * strongly discouraged.
+     *
+     * @param mode The mixed content mode to use. One of {@link #MIXED_CONTENT_NEVER_ALLOW},
+     *     {@link #MIXED_CONTENT_NEVER_ALLOW} or {@link #MIXED_CONTENT_COMPATIBILITY_MODE}.
+     */
+    public abstract void setMixedContentMode(int mode);
+
+    /**
+     * Gets the current behavior of the WebView with regard to loading insecure content from a
+     * secure origin.
+     * @return The current setting, one of {@link #MIXED_CONTENT_NEVER_ALLOW},
+     *     {@link #MIXED_CONTENT_NEVER_ALLOW} or {@link #MIXED_CONTENT_COMPATIBILITY_MODE}.
+     */
+    public abstract int getMixedContentMode();
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c914e52..d06cd75 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -33,6 +33,7 @@
 import android.os.Message;
 import android.os.StrictMode;
 import android.print.PrintDocumentAdapter;
+import android.security.KeyChain;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -701,7 +702,7 @@
      */
     @Deprecated
     public static void enablePlatformNotifications() {
-        getFactory().getStatics().setPlatformNotificationsEnabled(true);
+        // noop
     }
 
     /**
@@ -713,7 +714,7 @@
      */
     @Deprecated
     public static void disablePlatformNotifications() {
-        getFactory().getStatics().setPlatformNotificationsEnabled(false);
+        // noop
     }
 
     /**
@@ -1479,18 +1480,16 @@
      * Clears the client certificate preferences table stored in response
      * to proceeding/cancelling client cert requests. Note that webview
      * automatically clears these preferences when it receives a
-     * {@link KeyChain.ACTION_STORAGE_CHANGED}
+     * {@link KeyChain#ACTION_STORAGE_CHANGED} intent. The client certificate
+     * preferences are global for all Webviews.
      *
-     * @param resultCallback A callback to be invoked when client certs are cleared.
-     *                       The embedder can pass null if not interested in the callback.
-     *
-     * TODO(sgurun) unhide
-     * @hide
+     * @param onCleared  A runnable to be invoked when client certs are cleared.
+     *                   The embedder can pass null if not interested in the
+     *                   callback. The runnable will be called in UI thread.
      */
-    public void clearClientCertPreferences(ValueCallback<Void> resultCallback) {
-        checkThread();
+    public static void clearClientCertPreferences(Runnable onCleared) {
         if (DebugFlags.TRACE_API) Log.d(LOGTAG, "clearClientCertPreferences");
-        mProvider.clearClientCertPreferences(resultCallback);
+        getFactory().getStatics().clearClientCertPreferences(onCleared);
     }
 
     /**
@@ -1610,6 +1609,8 @@
      * @return the address, or if no address is found, null
      */
     public static String findAddress(String addr) {
+        // TODO: Rewrite this in Java so it is not needed to start up chromium
+        // Could also be deprecated
         return getFactory().getStatics().findAddress(addr);
     }
 
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 688c251..62b80c4a 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -19,6 +19,7 @@
 import android.graphics.Bitmap;
 import android.net.http.SslError;
 import android.os.Message;
+import android.view.InputEvent;
 import android.view.KeyEvent;
 import android.view.ViewRootImpl;
 
@@ -223,8 +224,6 @@
      * @param view The WebView that is initiating the callback
      * @param request An instance of a {@link ClientCertRequest}
      *
-     * TODO(sgurun) unhide
-     * @hide
      */
     public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
         request.cancel();
@@ -272,11 +271,43 @@
      *
      * @param view The WebView that is initiating the callback.
      * @param event The key event.
+     * @deprecated This method is subsumed by the more generic onUnhandledInputEvent.
      */
+    @Deprecated
     public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
+        onUnhandledInputEventInternal(view, event);
+    }
+
+    /**
+     * Notify the host application that a input event was not handled by the WebView.
+     * Except system keys, WebView always consumes input events in the normal flow
+     * or if shouldOverrideKeyEvent returns true. This is called asynchronously
+     * from where the event is dispatched. It gives the host application a chance
+     * to handle the unhandled input events.
+     *
+     * Note that if the event is a {@link android.view.MotionEvent}, then it's lifetime is only
+     * that of the function call. If the WebViewClient wishes to use the event beyond that, then it
+     * <i>must</i> create a copy of the event.
+     *
+     * It is the responsibility of overriders of this method to call
+     * {@link #onUnhandledKeyEvent(WebView, KeyEvent)}
+     * when appropriate if they wish to continue receiving events through it.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param event The input event.
+     */
+    public void onUnhandledInputEvent(WebView view, InputEvent event) {
+        if (event instanceof KeyEvent) {
+            onUnhandledKeyEvent(view, (KeyEvent) event);
+            return;
+        }
+        onUnhandledInputEventInternal(view, event);
+    }
+
+    private void onUnhandledInputEventInternal(WebView view, InputEvent event) {
         ViewRootImpl root = view.getViewRootImpl();
         if (root != null) {
-            root.dispatchUnhandledKey(event);
+            root.dispatchUnhandledInputEvent(event);
         }
     }
 
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index e391aaf..945e0e3 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -59,6 +59,13 @@
          * {@link android.webkit.WebView#setWebContentsDebuggingEnabled(boolean) }
          */
         void setWebContentsDebuggingEnabled(boolean enable);
+
+        /**
+         * Implements the API method:
+         * {@link android.webkit.WebView#clearClientCertPreferences(Runnable) }
+         */
+        void clearClientCertPreferences(Runnable onCleared);
+
     }
 
     Statics getStatics();
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index efa5497..5081ff5 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -198,8 +198,6 @@
 
     public void clearSslPreferences();
 
-    public void clearClientCertPreferences(ValueCallback<Void> resultCallback);
-
     public WebBackForwardList copyBackForwardList();
 
     public void setFindListener(WebView.FindListener listener);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index becda67..3fac883 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -110,6 +110,7 @@
      * @see #setTranscriptMode(int)
      */
     public static final int TRANSCRIPT_MODE_DISABLED = 0;
+
     /**
      * The list will automatically scroll to the bottom when a data set change
      * notification is received and only if the last item is already visible
@@ -118,6 +119,7 @@
      * @see #setTranscriptMode(int)
      */
     public static final int TRANSCRIPT_MODE_NORMAL = 1;
+
     /**
      * The list will automatically scroll to the bottom, no matter what items
      * are currently visible.
@@ -609,6 +611,9 @@
 
     final boolean[] mIsScrap = new boolean[1];
 
+    private final int[] mScrollOffset = new int[2];
+    private final int[] mScrollConsumed = new int[2];
+
     // True when the popup should be hidden because of a call to
     // dispatchDisplayHint()
     private boolean mPopupHidden;
@@ -2489,8 +2494,30 @@
         }
     }
 
+    /**
+     * Positions the selector in a way that mimics keyboard focus. If the
+     * selector drawable supports hotspots, this manages the focus hotspot.
+     */
+    void positionSelectorLikeFocus(int position, View sel) {
+        positionSelector(position, sel);
+
+        final Drawable selector = mSelector;
+        if (selector != null && selector.supportsHotspots() && position != INVALID_POSITION) {
+            final Rect bounds = mSelectorRect;
+            final float x = bounds.exactCenterX();
+            final float y = bounds.exactCenterY();
+            selector.setHotspot(R.attr.state_focused, x, y);
+        }
+    }
+
     void positionSelector(int position, View sel) {
         if (position != INVALID_POSITION) {
+            if (mSelectorPosition != position) {
+                final Drawable selector = mSelector;
+                if (selector != null && selector.supportsHotspots()) {
+                    selector.clearHotspots();
+                }
+            }
             mSelectorPosition = position;
         }
 
@@ -3240,13 +3267,14 @@
         }
     }
 
-    private boolean startScrollIfNeeded(int y) {
+    private boolean startScrollIfNeeded(int y, MotionEvent vtev) {
         // Check if we have moved far enough that it looks more like a
         // scroll than a tap
         final int deltaY = y - mMotionY;
         final int distance = Math.abs(deltaY);
         final boolean overscroll = mScrollY != 0;
-        if (overscroll || distance > mTouchSlop) {
+        if ((overscroll || distance > mTouchSlop) &&
+                (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) {
             createScrollingCache();
             if (overscroll) {
                 mTouchMode = TOUCH_MODE_OVERSCROLL;
@@ -3268,17 +3296,28 @@
             if (parent != null) {
                 parent.requestDisallowInterceptTouchEvent(true);
             }
-            scrollIfNeeded(y);
+            scrollIfNeeded(y, vtev);
             return true;
         }
 
         return false;
     }
 
-    private void scrollIfNeeded(int y) {
-        final int rawDeltaY = y - mMotionY;
+    private void scrollIfNeeded(int y, MotionEvent vtev) {
+        int rawDeltaY = y - mMotionY;
+        if (dispatchNestedPreScroll(0, rawDeltaY, mScrollConsumed, mScrollOffset)) {
+            rawDeltaY -= mScrollConsumed[1];
+            mMotionCorrection -= mScrollOffset[1];
+            if (mLastY != Integer.MIN_VALUE) {
+                mLastY -= mScrollOffset[1] + mScrollConsumed[1];
+            }
+            if (vtev != null) {
+                vtev.offsetLocation(0, mScrollOffset[1]);
+            }
+        }
         final int deltaY = rawDeltaY - mMotionCorrection;
         int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY;
+        int lastYCorrection = 0;
 
         if (mTouchMode == TOUCH_MODE_SCROLL) {
             if (PROFILE_SCROLLING) {
@@ -3337,39 +3376,46 @@
 
                         int overscroll = -incrementalDeltaY -
                                 (motionViewRealTop - motionViewPrevTop);
-                        overScrollBy(0, overscroll, 0, mScrollY, 0, 0,
-                                0, mOverscrollDistance, true);
-                        if (Math.abs(mOverscrollDistance) == Math.abs(mScrollY)) {
-                            // Don't allow overfling if we're at the edge.
-                            if (mVelocityTracker != null) {
-                                mVelocityTracker.clear();
+                        if (dispatchNestedScroll(0, overscroll - incrementalDeltaY, 0, overscroll,
+                                mScrollOffset)) {
+                            mMotionCorrection -= mScrollOffset[1];
+                            lastYCorrection -= mScrollOffset[1];
+                            vtev.offsetLocation(0, mScrollOffset[1]);
+                        } else {
+                            overScrollBy(0, overscroll, 0, mScrollY, 0, 0,
+                                    0, mOverscrollDistance, true);
+                            if (Math.abs(mOverscrollDistance) == Math.abs(mScrollY)) {
+                                // Don't allow overfling if we're at the edge.
+                                if (mVelocityTracker != null) {
+                                    mVelocityTracker.clear();
+                                }
                             }
-                        }
 
-                        final int overscrollMode = getOverScrollMode();
-                        if (overscrollMode == OVER_SCROLL_ALWAYS ||
-                                (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
-                                        !contentFits())) {
-                            mDirection = 0; // Reset when entering overscroll.
-                            mTouchMode = TOUCH_MODE_OVERSCROLL;
-                            if (rawDeltaY > 0) {
-                                mEdgeGlowTop.onPull((float) overscroll / getHeight());
-                                if (!mEdgeGlowBottom.isFinished()) {
-                                    mEdgeGlowBottom.onRelease();
+                            final int overscrollMode = getOverScrollMode();
+                            if (overscrollMode == OVER_SCROLL_ALWAYS ||
+                                    (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
+                                            !contentFits())) {
+                                mDirection = 0; // Reset when entering overscroll.
+                                mTouchMode = TOUCH_MODE_OVERSCROLL;
+                                if (deltaY > 0) {
+                                    mEdgeGlowTop.onPull((float) overscroll / getHeight());
+                                    if (!mEdgeGlowBottom.isFinished()) {
+                                        mEdgeGlowBottom.onRelease();
+                                    }
+                                    invalidate(mEdgeGlowTop.getBounds(false));
+                                } else if (deltaY < 0) {
+                                    mEdgeGlowBottom.onPull((float) overscroll / getHeight());
+                                    if (!mEdgeGlowTop.isFinished()) {
+                                        mEdgeGlowTop.onRelease();
+                                    }
+                                    invalidate(mEdgeGlowBottom.getBounds(true));
                                 }
-                                invalidate(mEdgeGlowTop.getBounds(false));
-                            } else if (rawDeltaY < 0) {
-                                mEdgeGlowBottom.onPull((float) overscroll / getHeight());
-                                if (!mEdgeGlowTop.isFinished()) {
-                                    mEdgeGlowTop.onRelease();
-                                }
-                                invalidate(mEdgeGlowBottom.getBounds(true));
                             }
                         }
                     }
                     mMotionY = y;
                 }
-                mLastY = y;
+                mLastY = y + lastYCorrection;
             }
         } else if (mTouchMode == TOUCH_MODE_OVERSCROLL) {
             if (y != mLastY) {
@@ -3493,6 +3539,8 @@
             return false;
         }
 
+        startNestedScroll(SCROLL_AXIS_VERTICAL);
+
         if (mFastScroll != null) {
             boolean intercepted = mFastScroll.onTouchEvent(ev);
             if (intercepted) {
@@ -3501,7 +3549,7 @@
         }
 
         initVelocityTrackerIfNotExists();
-        mVelocityTracker.addMovement(ev);
+        final MotionEvent vtev = MotionEvent.obtain(ev);
 
         final int actionMasked = ev.getActionMasked();
         switch (actionMasked) {
@@ -3511,7 +3559,7 @@
             }
 
             case MotionEvent.ACTION_MOVE: {
-                onTouchMove(ev);
+                onTouchMove(ev, vtev);
                 break;
             }
 
@@ -3562,6 +3610,10 @@
             }
         }
 
+        if (mVelocityTracker != null) {
+            mVelocityTracker.addMovement(vtev);
+        }
+        vtev.recycle();
         return true;
     }
 
@@ -3628,7 +3680,7 @@
         }
     }
 
-    private void onTouchMove(MotionEvent ev) {
+    private void onTouchMove(MotionEvent ev, MotionEvent vtev) {
         int pointerIndex = ev.findPointerIndex(mActivePointerId);
         if (pointerIndex == -1) {
             pointerIndex = 0;
@@ -3649,7 +3701,7 @@
             case TOUCH_MODE_DONE_WAITING:
                 // Check if we have moved far enough that it looks more like a
                 // scroll than a tap. If so, we'll enter scrolling mode.
-                if (startScrollIfNeeded(y)) {
+                if (startScrollIfNeeded(y, vtev)) {
                     break;
                 }
                 // Otherwise, check containment within list bounds. If we're
@@ -3669,7 +3721,7 @@
                 break;
             case TOUCH_MODE_SCROLL:
             case TOUCH_MODE_OVERSCROLL:
-                scrollIfNeeded(y);
+                scrollIfNeeded(y, vtev);
                 break;
         }
     }
@@ -3911,6 +3963,49 @@
     }
 
     @Override
+    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
+        return ((nestedScrollAxes & SCROLL_AXIS_VERTICAL) != 0);
+    }
+
+    @Override
+    public void onNestedScrollAccepted(View child, View target, int axes) {
+        super.onNestedScrollAccepted(child, target, axes);
+        startNestedScroll(SCROLL_AXIS_VERTICAL);
+    }
+
+    @Override
+    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+            int dxUnconsumed, int dyUnconsumed) {
+        final int motionIndex = getChildCount() / 2;
+        final View motionView = getChildAt(motionIndex);
+        final int oldTop = motionView != null ? motionView.getTop() : 0;
+        if (motionView == null || trackMotionScroll(-dyUnconsumed, -dyUnconsumed)) {
+            int myUnconsumed = dyUnconsumed;
+            int myConsumed = 0;
+            if (motionView != null) {
+                myConsumed = motionView.getTop() - oldTop;
+                myUnconsumed -= myConsumed;
+            }
+            dispatchNestedScroll(0, myConsumed, 0, myUnconsumed, null);
+        }
+    }
+
+    @Override
+    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
+        final int childCount = getChildCount();
+        if (!consumed && childCount > 0 && canScrollList((int) velocityY) &&
+                Math.abs(velocityY) > mMinimumVelocity) {
+            reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
+            if (mFlingRunnable == null) {
+                mFlingRunnable = new FlingRunnable();
+            }
+            mFlingRunnable.start((int) velocityY);
+            return true;
+        }
+        return dispatchNestedFling(velocityX, velocityY, consumed);
+    }
+
+    @Override
     public void draw(Canvas canvas) {
         super.draw(canvas);
         if (mEdgeGlowTop != null) {
@@ -4046,6 +4141,7 @@
             mLastY = Integer.MIN_VALUE;
             initOrResetVelocityTracker();
             mVelocityTracker.addMovement(ev);
+            startNestedScroll(SCROLL_AXIS_VERTICAL);
             if (touchMode == TOUCH_MODE_FLING) {
                 return true;
             }
@@ -4063,7 +4159,7 @@
                 final int y = (int) ev.getY(pointerIndex);
                 initVelocityTrackerIfNotExists();
                 mVelocityTracker.addMovement(ev);
-                if (startScrollIfNeeded(y)) {
+                if (startScrollIfNeeded(y, null)) {
                     return true;
                 }
                 break;
@@ -4077,6 +4173,7 @@
             mActivePointerId = INVALID_POINTER;
             recycleVelocityTracker();
             reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+            stopNestedScroll();
             break;
         }
 
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index b47177a..10ec105 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -1565,7 +1565,7 @@
 
             // Ensure that keyboard focus starts from the last touched position.
             setSelectedPositionInt(position);
-            positionSelector(position, child);
+            positionSelectorLikeFocus(position, child);
 
             // Refresh the drawable state to reflect the new pressed state,
             // which will also update the selector state.
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 5de67c8..eeb8015 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2564,7 +2564,7 @@
 
         if (needToRedraw) {
             if (selectedView != null) {
-                positionSelector(selectedPos, selectedView);
+                positionSelectorLikeFocus(selectedPos, selectedView);
                 mSelectedTop = selectedView.getTop();
             }
             if (!awakenScrollBars()) {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 7e8f6b4..8dfef25a 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -583,7 +583,8 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         initVelocityTrackerIfNotExists();
-        mVelocityTracker.addMovement(ev);
+
+        MotionEvent vtev = MotionEvent.obtain(ev);
 
         final int action = ev.getAction();
 
@@ -628,6 +629,7 @@
                 int deltaY = mLastMotionY - y;
                 if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
                     deltaY -= mScrollConsumed[1] + mScrollOffset[1];
+                    vtev.offsetLocation(0, mScrollOffset[1]);
                 }
                 if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
                     final ViewParent parent = getParent();
@@ -663,6 +665,7 @@
                     final int unconsumedY = deltaY - scrolledDeltaY;
                     if (dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, mScrollOffset)) {
                         mLastMotionY -= mScrollOffset[1];
+                        vtev.offsetLocation(0, mScrollOffset[1]);
                     } else if (canOverscroll) {
                         final int pulledToY = oldY + deltaY;
                         if (pulledToY < 0) {
@@ -720,6 +723,11 @@
                 mLastMotionY = (int) ev.getY(ev.findPointerIndex(mActivePointerId));
                 break;
         }
+
+        if (mVelocityTracker != null) {
+            mVelocityTracker.addMovement(vtev);
+        }
+        vtev.recycle();
         return true;
     }
 
@@ -1565,10 +1573,10 @@
     }
 
     private void flingWithNestedDispatch(int velocityY) {
-        if (mScrollY == 0 && velocityY < 0 ||
-                mScrollY == getScrollRange() && velocityY > 0) {
-            dispatchNestedFling(0, velocityY);
-        } else {
+        final boolean canFling = (mScrollY > 0 || velocityY > 0) &&
+                (mScrollY < getScrollRange() || velocityY < 0);
+        dispatchNestedFling(0, velocityY, canFling);
+        if (canFling) {
             fling(velocityY);
         }
     }
@@ -1627,6 +1635,12 @@
         return (nestedScrollAxes & SCROLL_AXIS_VERTICAL) != 0;
     }
 
+    @Override
+    public void onNestedScrollAccepted(View child, View target, int axes) {
+        super.onNestedScrollAccepted(child, target, axes);
+        startNestedScroll(SCROLL_AXIS_VERTICAL);
+    }
+
     /**
      * @inheritDoc
      */
@@ -1638,16 +1652,23 @@
     @Override
     public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
             int dxUnconsumed, int dyUnconsumed) {
+        final int oldScrollY = mScrollY;
         scrollBy(0, dyUnconsumed);
+        final int myConsumed = mScrollY - oldScrollY;
+        final int myUnconsumed = dyUnconsumed - myConsumed;
+        dispatchNestedScroll(0, myConsumed, 0, myUnconsumed, null);
     }
 
     /**
      * @inheritDoc
      */
     @Override
-    public boolean onNestedFling(View target, float velocityX, float velocityY) {
-        flingWithNestedDispatch((int) velocityY);
-        return true;
+    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
+        if (!consumed) {
+            flingWithNestedDispatch((int) velocityY);
+            return true;
+        }
+        return false;
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 3219ddd..98e35dd 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -24,8 +24,9 @@
 import android.service.voice.IVoiceInteractionSession;
 
 interface IVoiceInteractionManagerService {
-    void startVoiceActivity(in Intent intent, String resolvedType, IVoiceInteractionService service,
-            in Bundle sessionArgs);
-    int deliverNewSession(IBinder token, IVoiceInteractionSession session,
+    void startSession(IVoiceInteractionService service, in Bundle sessionArgs);
+    boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
             IVoiceInteractor interactor);
+    int startVoiceActivity(IBinder token, in Intent intent, String resolvedType);
+    void finish(IBinder token);
 }
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
new file mode 100644
index 0000000..2f74372
--- /dev/null
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.app.Activity;
+import android.app.AppGlobals;
+import android.os.Bundle;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.app.ActivityManagerNative;
+import android.os.RemoteException;
+import android.util.Slog;
+import java.util.List;
+import java.util.Set;
+
+
+
+
+/*
+ * This is used in conjunction with DevicePolicyManager.setForwardingIntents to enable intents to be
+ * passed in and out of a managed profile.
+ */
+
+public class IntentForwarderActivity extends Activity  {
+
+    public static String TAG = "IntentForwarderActivity";
+
+    public static String FORWARD_INTENT_TO_USER_OWNER
+            = "com.android.internal.app.ForwardIntentToUserOwner";
+
+    public static String FORWARD_INTENT_TO_MANAGED_PROFILE
+            = "com.android.internal.app.ForwardIntentToManagedProfile";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Intent intentReceived = getIntent();
+
+        String className = intentReceived.getComponent().getClassName();
+        final UserHandle userDest;
+
+        if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) {
+            userDest = UserHandle.OWNER;
+        } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+            userDest = getManagedProfile();
+        } else {
+            Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly");
+            userDest = null;
+        }
+        if (userDest == null) { // This covers the case where there is no managed profile.
+            finish();
+            return;
+        }
+        Intent newIntent = new Intent(intentReceived);
+        newIntent.setComponent(null);
+        newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
+                |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
+        int callingUserId = getUserId();
+        IPackageManager ipm = AppGlobals.getPackageManager();
+        String resolvedType = newIntent.resolveTypeIfNeeded(getContentResolver());
+        boolean canForward = false;
+        try {
+            canForward = ipm.canForwardTo(newIntent, resolvedType, callingUserId,
+                    userDest.getIdentifier());
+        } catch (RemoteException e) {
+            Slog.e(TAG, "PackageManagerService is dead?");
+        }
+        if (canForward) {
+            startActivityAsUser(newIntent, userDest);
+        } else {
+            Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user "
+                    + callingUserId + " to user " + userDest.getIdentifier());
+        }
+        finish();
+    }
+
+    /**
+     * Returns the managed profile for this device or null if there is no managed
+     * profile.
+     *
+     * TODO: Remove the assumption that there is only one managed profile
+     * on the device.
+     */
+    private UserHandle getManagedProfile() {
+        UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+        List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER);
+        for (UserInfo userInfo : relatedUsers) {
+            if (userInfo.isManagedProfile()) return new UserHandle(userInfo.id);
+        }
+        Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE
+                + " has been called, but there is no managed profile");
+        return null;
+    }
+}
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 131f828..66548f0 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -17,7 +17,9 @@
 package com.android.internal.app;
 
 import android.animation.ValueAnimator;
+import android.content.res.TypedArray;
 import android.view.ViewParent;
+import com.android.internal.R;
 import com.android.internal.view.ActionBarPolicy;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuPopupHelper;
@@ -41,7 +43,6 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
-import android.os.Handler;
 import android.util.TypedValue;
 import android.view.ActionMode;
 import android.view.ContextThemeWrapper;
@@ -57,7 +58,6 @@
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Map;
 
 /**
  * WindowDecorActionBar is the ActionBar implementation used
@@ -66,7 +66,8 @@
  * across both the ActionBarView at the top of the screen and
  * a horizontal LinearLayout at the bottom which is normally hidden.
  */
-public class WindowDecorActionBar extends ActionBar {
+public class WindowDecorActionBar extends ActionBar implements
+        ActionBarOverlayLayout.ActionBarVisibilityCallback {
     private static final String TAG = "WindowDecorActionBar";
 
     private Context mContext;
@@ -116,6 +117,7 @@
 
     private Animator mCurrentShowAnim;
     private boolean mShowHideAnimationEnabled;
+    boolean mHideOnContentScroll;
 
     final AnimatorListener mHideListener = new AnimatorListenerAdapter() {
         @Override
@@ -132,7 +134,7 @@
             mCurrentShowAnim = null;
             completeDeferredDestroyActionMode();
             if (mOverlayLayout != null) {
-                mOverlayLayout.requestFitSystemWindows();
+                mOverlayLayout.requestApplyInsets();
             }
         }
     };
@@ -183,7 +185,7 @@
         mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
                 com.android.internal.R.id.action_bar_overlay_layout);
         if (mOverlayLayout != null) {
-            mOverlayLayout.setActionBar(this);
+            mOverlayLayout.setActionBarVisibilityCallback(this);
         }
         mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
         mContextView = (ActionBarContextView) decor.findViewById(
@@ -213,6 +215,14 @@
         ActionBarPolicy abp = ActionBarPolicy.get(mContext);
         setHomeButtonEnabled(abp.enableHomeButtonByDefault() || homeAsUp);
         setHasEmbeddedTabs(abp.hasEmbeddedTabs());
+
+        final TypedArray a = mContext.obtainStyledAttributes(null,
+                com.android.internal.R.styleable.ActionBar,
+                com.android.internal.R.attr.actionBarStyle, 0);
+        if (a.getBoolean(R.styleable.ActionBar_hideOnContentScroll, false)) {
+            setHideOnContentScrollEnabled(true);
+        }
+        a.recycle();
     }
 
     public void onConfigurationChanged(Configuration newConfig) {
@@ -234,17 +244,14 @@
             if (isInTabMode) {
                 mTabScrollView.setVisibility(View.VISIBLE);
                 if (mOverlayLayout != null) {
-                    mOverlayLayout.requestFitSystemWindows();
+                    mOverlayLayout.requestApplyInsets();
                 }
             } else {
                 mTabScrollView.setVisibility(View.GONE);
             }
         }
         mActionView.setCollapsable(!mHasEmbeddedTabs && isInTabMode);
-    }
-
-    public boolean hasNonEmbeddedTabs() {
-        return !mHasEmbeddedTabs && getNavigationMode() == NAVIGATION_MODE_TABS;
+        mOverlayLayout.setHasNonEmbeddedTabs(!mHasEmbeddedTabs && isInTabMode);
     }
 
     private void ensureTabsExist() {
@@ -279,7 +286,7 @@
         }
     }
 
-    public void setWindowVisibility(int visibility) {
+    public void onWindowVisibilityChanged(int visibility) {
         mCurWindowVisibility = visibility;
     }
 
@@ -453,6 +460,7 @@
             mActionMode.finish();
         }
 
+        mOverlayLayout.setHideOnContentScrollEnabled(false);
         mContextView.killMode();
         ActionModeImpl mode = new ActionModeImpl(callback);
         if (mode.dispatchOnCreate()) {
@@ -464,7 +472,7 @@
                 if (mSplitView.getVisibility() != View.VISIBLE) {
                     mSplitView.setVisibility(View.VISIBLE);
                     if (mOverlayLayout != null) {
-                        mOverlayLayout.requestFitSystemWindows();
+                        mOverlayLayout.requestApplyInsets();
                     }
                 }
             }
@@ -652,6 +660,35 @@
         }
     }
 
+    @Override
+    public void setHideOnContentScrollEnabled(boolean hideOnContentScroll) {
+        if (hideOnContentScroll && !mOverlayLayout.isInOverlayMode()) {
+            throw new IllegalStateException("Action bar must be in overlay mode " +
+                    "(Window.FEATURE_OVERLAY_ACTION_BAR) to enable hide on content scroll");
+        }
+        mHideOnContentScroll = hideOnContentScroll;
+        mOverlayLayout.setHideOnContentScrollEnabled(hideOnContentScroll);
+    }
+
+    @Override
+    public boolean isHideOnContentScrollEnabled() {
+        return mOverlayLayout.isHideOnContentScrollEnabled();
+    }
+
+    @Override
+    public int getHideOffset() {
+        return mOverlayLayout.getActionBarHideOffset();
+    }
+
+    @Override
+    public void setHideOffset(int offset) {
+        if (offset != 0 && !mOverlayLayout.isInOverlayMode()) {
+            throw new IllegalStateException("Action bar must be in overlay mode " +
+                    "(Window.FEATURE_OVERLAY_ACTION_BAR) to set a non-zero hide offset");
+        }
+        mOverlayLayout.setActionBarHideOffset(offset);
+    }
+
     private static boolean checkShowingFlags(boolean hiddenByApp, boolean hiddenBySystem,
             boolean showingForMode) {
         if (showingForMode) {
@@ -737,7 +774,7 @@
             mShowListener.onAnimationEnd(null);
         }
         if (mOverlayLayout != null) {
-            mOverlayLayout.requestFitSystemWindows();
+            mOverlayLayout.requestApplyInsets();
         }
     }
 
@@ -781,11 +818,7 @@
     }
 
     public boolean isShowing() {
-        return mNowShowing;
-    }
-
-    public boolean isSystemShowing() {
-        return !mHiddenBySystem;
+        return mNowShowing && getHideOffset() < getHeight();
     }
 
     void animateToMode(boolean toActionMode) {
@@ -844,6 +877,18 @@
         mActionView.setHomeActionContentDescription(resId);
     }
 
+    @Override
+    public void onContentScrollStarted() {
+        if (mCurrentShowAnim != null) {
+            mCurrentShowAnim.cancel();
+            mCurrentShowAnim = null;
+        }
+    }
+
+    @Override
+    public void onContentScrollStopped() {
+    }
+
     /**
      * @hide 
      */
@@ -894,6 +939,7 @@
             // Clear out the context mode views after the animation finishes
             mContextView.closeMode();
             mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+            mOverlayLayout.setHideOnContentScrollEnabled(mHideOnContentScroll);
 
             mActionMode = null;
         }
@@ -1204,6 +1250,7 @@
                 break;
         }
         mActionView.setCollapsable(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs);
+        mOverlayLayout.setHasNonEmbeddedTabs(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs);
     }
 
     @Override
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index dcc0a4c..cba09d1 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.inputmethod;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
 
 import android.content.Context;
@@ -119,14 +120,14 @@
         }
     }
 
-    private static class InputMethodAndSubtypeCircularList {
+    private static class InputMethodAndSubtypeList {
         private final Context mContext;
         // Used to load label
         private final PackageManager mPm;
         private final String mSystemLocaleStr;
         private final InputMethodSettings mSettings;
 
-        public InputMethodAndSubtypeCircularList(Context context, InputMethodSettings settings) {
+        public InputMethodAndSubtypeList(Context context, InputMethodSettings settings) {
             mContext = context;
             mSettings = settings;
             mPm = context.getPackageManager();
@@ -152,38 +153,6 @@
                             }
                         });
 
-        public ImeSubtypeListItem getNextInputMethod(
-                boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
-            if (imi == null) {
-                return null;
-            }
-            final List<ImeSubtypeListItem> imList =
-                    getSortedInputMethodAndSubtypeList();
-            if (imList.size() <= 1) {
-                return null;
-            }
-            final int N = imList.size();
-            final int currentSubtypeId =
-                    subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi,
-                            subtype.hashCode()) : NOT_A_SUBTYPE_ID;
-            for (int i = 0; i < N; ++i) {
-                final ImeSubtypeListItem isli = imList.get(i);
-                if (isli.mImi.equals(imi) && isli.mSubtypeId == currentSubtypeId) {
-                    if (!onlyCurrentIme) {
-                        return imList.get((i + 1) % N);
-                    }
-                    for (int j = 0; j < N - 1; ++j) {
-                        final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
-                        if (candidate.mImi.equals(imi)) {
-                            return candidate;
-                        }
-                    }
-                    return null;
-                }
-            }
-            return null;
-        }
-
         public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList() {
             return getSortedInputMethodAndSubtypeList(true, false, false);
         }
@@ -247,7 +216,38 @@
     private final ArrayDeque<SubtypeParams> mTypedSubtypeHistory = new ArrayDeque<SubtypeParams>();
     private final Object mLock = new Object();
     private final InputMethodSettings mSettings;
-    private InputMethodAndSubtypeCircularList mSubtypeList;
+    private InputMethodAndSubtypeList mSubtypeList;
+
+    @VisibleForTesting
+    public static ImeSubtypeListItem getNextInputMethodImpl(List<ImeSubtypeListItem> imList,
+            boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (imi == null) {
+            return null;
+        }
+        if (imList.size() <= 1) {
+            return null;
+        }
+        final int N = imList.size();
+        final int currentSubtypeId =
+                subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi,
+                        subtype.hashCode()) : NOT_A_SUBTYPE_ID;
+        for (int i = 0; i < N; ++i) {
+            final ImeSubtypeListItem isli = imList.get(i);
+            if (isli.mImi.equals(imi) && isli.mSubtypeId == currentSubtypeId) {
+                if (!onlyCurrentIme) {
+                    return imList.get((i + 1) % N);
+                }
+                for (int j = 0; j < N - 1; ++j) {
+                    final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
+                    if (candidate.mImi.equals(imi)) {
+                        return candidate;
+                    }
+                }
+                return null;
+            }
+        }
+        return null;
+    }
 
     public InputMethodSubtypeSwitchingController(InputMethodSettings settings) {
         mSettings = settings;
@@ -278,14 +278,15 @@
 
     public void resetCircularListLocked(Context context) {
         synchronized(mLock) {
-            mSubtypeList = new InputMethodAndSubtypeCircularList(context, mSettings);
+            mSubtypeList = new InputMethodAndSubtypeList(context, mSettings);
         }
     }
 
     public ImeSubtypeListItem getNextInputMethod(
             boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
         synchronized(mLock) {
-            return mSubtypeList.getNextInputMethod(onlyCurrentIme, imi, subtype);
+            return getNextInputMethodImpl(mSubtypeList.getSortedInputMethodAndSubtypeList(),
+                    onlyCurrentIme, imi, subtype);
         }
     }
 
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index a54b364..f6722a6 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -30,7 +30,7 @@
      * @return the non-null reference that was validated
      * @throws NullPointerException if {@code reference} is null
      */
-    public static <T> T checkNotNull(T reference) {
+    public static <T> T checkNotNull(final T reference) {
         if (reference == null) {
             throw new NullPointerException();
         }
@@ -47,7 +47,7 @@
      * @return the non-null reference that was validated
      * @throws NullPointerException if {@code reference} is null
      */
-    public static <T> T checkNotNull(T reference, Object errorMessage) {
+    public static <T> T checkNotNull(final T reference, final Object errorMessage) {
         if (reference == null) {
             throw new NullPointerException(String.valueOf(errorMessage));
         }
@@ -61,7 +61,7 @@
      * @param expression a boolean expression
      * @throws IllegalStateException if {@code expression} is false
      */
-    public static void checkState(boolean expression) {
+    public static void checkState(final boolean expression) {
         if (!expression) {
             throw new IllegalStateException();
         }
@@ -71,11 +71,178 @@
      * Check the requested flags, throwing if any requested flags are outside
      * the allowed set.
      */
-    public static void checkFlagsArgument(int requestedFlags, int allowedFlags) {
+    public static void checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
         if ((requestedFlags & allowedFlags) != requestedFlags) {
             throw new IllegalArgumentException("Requested flags 0x"
                     + Integer.toHexString(requestedFlags) + ", but only 0x"
                     + Integer.toHexString(allowedFlags) + " are allowed");
         }
     }
+
+    /**
+     * Ensures that that the argument numeric value is non-negative.
+     *
+     * @param value a numeric int value
+     * @param errorMessage the exception message to use if the check fails
+     * @return the validated numeric value
+     * @throws IllegalArgumentException if {@code value} was negative
+     */
+    public static int checkArgumentNonnegative(final int value, final String errorMessage) {
+        if (value < 0) {
+            throw new IllegalArgumentException(errorMessage);
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that that the argument numeric value is non-negative.
+     *
+     * @param value a numeric long value
+     * @param errorMessage the exception message to use if the check fails
+     * @return the validated numeric value
+     * @throws IllegalArgumentException if {@code value} was negative
+     */
+    public static long checkArgumentNonnegative(final long value, final String errorMessage) {
+        if (value < 0) {
+            throw new IllegalArgumentException(errorMessage);
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that that the argument numeric value is positive.
+     *
+     * @param value a numeric int value
+     * @param errorMessage the exception message to use if the check fails
+     * @return the validated numeric value
+     * @throws IllegalArgumentException if {@code value} was not positive
+     */
+    public static int checkArgumentPositive(final int value, final String errorMessage) {
+        if (value <= 0) {
+            throw new IllegalArgumentException(errorMessage);
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the argument floating point value is a finite number.
+     *
+     * <p>A finite number is defined to be both representable (that is, not NaN) and
+     * not infinite (that is neither positive or negative infinity).</p>
+     *
+     * @param value a floating point value
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated floating point value
+     *
+     * @throws IllegalArgumentException if {@code value} was not finite
+     */
+    public static float checkArgumentFinite(final float value, final String valueName) {
+        if (Float.isNaN(value)) {
+            throw new IllegalArgumentException(valueName + " must not be NaN");
+        } else if (Float.isInfinite(value)) {
+            throw new IllegalArgumentException(valueName + " must not be infinite");
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the argument floating point value is within the inclusive range.
+     *
+     * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
+     * will always be out of range.</p>
+     *
+     * @param value a floating point value
+     * @param lower the lower endpoint of the inclusive range
+     * @param upper the upper endpoint of the inclusive range
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated floating point value
+     *
+     * @throws IllegalArgumentException if {@code value} was not within the range
+     */
+    public static float checkArgumentInRange(float value, float lower, float upper,
+            String valueName) {
+        if (Float.isNaN(value)) {
+            throw new IllegalArgumentException(valueName + " must not be NaN");
+        } else if (value < lower) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
+        } else if (value > upper) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the array is not {@code null}, and none if its elements are {@code null}.
+     *
+     * @param value an array of boxed objects
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated array
+     *
+     * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
+     */
+    public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
+        if (value == null) {
+            throw new NullPointerException(valueName + " must not be null");
+        }
+
+        for (int i = 0; i < value.length; ++i) {
+            if (value[i] == null) {
+                throw new NullPointerException(
+                        String.format("%s[%d] must not be null", valueName, i));
+            }
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that all elements in the argument floating point array are within the inclusive range
+     *
+     * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
+     * will always be out of range.</p>
+     *
+     * @param value a floating point array of values
+     * @param lower the lower endpoint of the inclusive range
+     * @param upper the upper endpoint of the inclusive range
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated floating point value
+     *
+     * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
+     * @throws NullPointerException if the {@code value} was {@code null}
+     */
+    public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
+            String valueName) {
+        checkNotNull(value, valueName + " must not be null");
+
+        for (int i = 0; i < value.length; ++i) {
+            float v = value[i];
+
+            if (Float.isNaN(v)) {
+                throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
+            } else if (v < lower) {
+                throw new IllegalArgumentException(
+                        String.format("%s[%d] is out of range of [%f, %f] (too low)",
+                                valueName, i, lower, upper));
+            } else if (v > upper) {
+                throw new IllegalArgumentException(
+                        String.format("%s[%d] is out of range of [%f, %f] (too high)",
+                                valueName, i, lower, upper));
+            }
+        }
+
+        return value;
+    }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index c9dff1a..19d58bf 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -16,18 +16,22 @@
 
 package com.android.internal.widget;
 
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.os.Build;
-import android.view.ViewGroup;
-import android.view.WindowInsets;
-import com.android.internal.app.WindowDecorActionBar;
-
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.util.AttributeSet;
+import android.util.IntProperty;
+import android.util.Property;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
+import android.view.WindowInsets;
+import android.widget.OverScroller;
 
 /**
  * Special layout for the containing of an overlay action bar (and its
@@ -38,7 +42,7 @@
     private static final String TAG = "ActionBarOverlayLayout";
 
     private int mActionBarHeight;
-    private WindowDecorActionBar mActionBar;
+    //private WindowDecorActionBar mActionBar;
     private int mWindowVisibility = View.VISIBLE;
 
     // The main UI elements that we handle the layout of.
@@ -54,6 +58,10 @@
     private boolean mIgnoreWindowContentOverlay;
 
     private boolean mOverlayMode;
+    private boolean mHasNonEmbeddedTabs;
+    private boolean mHideOnContentScroll;
+    private boolean mAnimatingForFling;
+    private int mHideOnContentScrollReference;
     private int mLastSystemUiVisibility;
     private final Rect mBaseContentInsets = new Rect();
     private final Rect mLastBaseContentInsets = new Rect();
@@ -62,6 +70,84 @@
     private final Rect mInnerInsets = new Rect();
     private final Rect mLastInnerInsets = new Rect();
 
+    private ActionBarVisibilityCallback mActionBarVisibilityCallback;
+
+    private final int ACTION_BAR_ANIMATE_DELAY = 600; // ms
+
+    private OverScroller mFlingEstimator;
+
+    private ViewPropertyAnimator mCurrentActionBarTopAnimator;
+    private ViewPropertyAnimator mCurrentActionBarBottomAnimator;
+
+    private final Animator.AnimatorListener mTopAnimatorListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mCurrentActionBarTopAnimator = null;
+            mAnimatingForFling = false;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mCurrentActionBarTopAnimator = null;
+            mAnimatingForFling = false;
+        }
+    };
+
+    private final Animator.AnimatorListener mBottomAnimatorListener =
+            new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mCurrentActionBarBottomAnimator = null;
+            mAnimatingForFling = false;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mCurrentActionBarBottomAnimator = null;
+            mAnimatingForFling = false;
+        }
+    };
+
+    private final Runnable mRemoveActionBarHideOffset = new Runnable() {
+        public void run() {
+            haltActionBarHideOffsetAnimations();
+            mCurrentActionBarTopAnimator = mActionBarTop.animate().translationY(0)
+                    .setListener(mTopAnimatorListener);
+            if (mActionBarBottom != null && mActionBarBottom.getVisibility() != GONE) {
+                mCurrentActionBarBottomAnimator = mActionBarBottom.animate().translationY(0)
+                        .setListener(mBottomAnimatorListener);
+            }
+        }
+    };
+
+    private final Runnable mAddActionBarHideOffset = new Runnable() {
+        public void run() {
+            haltActionBarHideOffsetAnimations();
+            mCurrentActionBarTopAnimator = mActionBarTop.animate()
+                    .translationY(-mActionBarTop.getHeight())
+                    .setListener(mTopAnimatorListener);
+            if (mActionBarBottom != null && mActionBarBottom.getVisibility() != GONE) {
+                mCurrentActionBarBottomAnimator = mActionBarBottom.animate()
+                        .translationY(mActionBarBottom.getHeight())
+                        .setListener(mBottomAnimatorListener);
+            }
+        }
+    };
+
+    public static final Property<ActionBarOverlayLayout, Integer> ACTION_BAR_HIDE_OFFSET =
+            new IntProperty<ActionBarOverlayLayout>("actionBarHideOffset") {
+
+                @Override
+                public void setValue(ActionBarOverlayLayout object, int value) {
+                    object.setActionBarHideOffset(value);
+                }
+
+                @Override
+                public Integer get(ActionBarOverlayLayout object) {
+                    return object.getActionBarHideOffset();
+                }
+            };
+
     static final int[] ATTRS = new int [] {
             com.android.internal.R.attr.actionBarSize,
             com.android.internal.R.attr.windowContentOverlay
@@ -86,14 +172,22 @@
 
         mIgnoreWindowContentOverlay = context.getApplicationInfo().targetSdkVersion <
                 Build.VERSION_CODES.KITKAT;
+
+        mFlingEstimator = new OverScroller(context);
     }
 
-    public void setActionBar(WindowDecorActionBar impl) {
-        mActionBar = impl;
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        haltActionBarHideOffsetAnimations();
+    }
+
+    public void setActionBarVisibilityCallback(ActionBarVisibilityCallback cb) {
+        mActionBarVisibilityCallback = cb;
         if (getWindowToken() != null) {
             // This is being initialized after being added to a window;
             // make sure to update all state now.
-            mActionBar.setWindowVisibility(mWindowVisibility);
+            mActionBarVisibilityCallback.onWindowVisibilityChanged(mWindowVisibility);
             if (mLastSystemUiVisibility != 0) {
                 int newVis = mLastSystemUiVisibility;
                 onWindowSystemUiVisibilityChanged(newVis);
@@ -114,6 +208,14 @@
                         Build.VERSION_CODES.KITKAT;
     }
 
+    public boolean isInOverlayMode() {
+        return mOverlayMode;
+    }
+
+    public void setHasNonEmbeddedTabs(boolean hasNonEmbeddedTabs) {
+        mHasNonEmbeddedTabs = hasNonEmbeddedTabs;
+    }
+
     public void setShowingForActionMode(boolean showing) {
         if (showing) {
             // Here's a fun hack: if the status bar is currently being hidden,
@@ -140,19 +242,18 @@
         pullChildren();
         final int diff = mLastSystemUiVisibility ^ visible;
         mLastSystemUiVisibility = visible;
-        final boolean barVisible = (visible&SYSTEM_UI_FLAG_FULLSCREEN) == 0;
-        final boolean wasVisible = mActionBar != null ? mActionBar.isSystemShowing() : true;
-        final boolean stable = (visible&SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;
-        if (mActionBar != null) {
+        final boolean barVisible = (visible & SYSTEM_UI_FLAG_FULLSCREEN) == 0;
+        final boolean stable = (visible & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;
+        if (mActionBarVisibilityCallback != null) {
             // We want the bar to be visible if it is not being hidden,
             // or the app has not turned on a stable UI mode (meaning they
             // are performing explicit layout around the action bar).
-            mActionBar.enableContentAnimations(!stable);
-            if (barVisible || !stable) mActionBar.showForSystem();
-            else mActionBar.hideForSystem();
+            mActionBarVisibilityCallback.enableContentAnimations(!stable);
+            if (barVisible || !stable) mActionBarVisibilityCallback.showForSystem();
+            else mActionBarVisibilityCallback.hideForSystem();
         }
-        if ((diff&SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
-            if (mActionBar != null) {
+        if ((diff & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
+            if (mActionBarVisibilityCallback != null) {
                 requestApplyInsets();
             }
         }
@@ -162,8 +263,8 @@
     protected void onWindowVisibilityChanged(int visibility) {
         super.onWindowVisibilityChanged(visibility);
         mWindowVisibility = visibility;
-        if (mActionBar != null) {
-            mActionBar.setWindowVisibility(visibility);
+        if (mActionBarVisibilityCallback != null) {
+            mActionBarVisibilityCallback.onWindowVisibilityChanged(visibility);
         }
     }
 
@@ -279,8 +380,8 @@
             // This is the standard space needed for the action bar.  For stable measurement,
             // we can't depend on the size currently reported by it -- this must remain constant.
             topInset = mActionBarHeight;
-            if (mActionBar != null && mActionBar.hasNonEmbeddedTabs()) {
-                View tabs = mActionBarTop.getTabContainer();
+            if (mHasNonEmbeddedTabs) {
+                final View tabs = mActionBarTop.getTabContainer();
                 if (tabs != null) {
                     // If tabs are not embedded, increase space on top to account for them.
                     topInset += mActionBarHeight;
@@ -395,16 +496,138 @@
         return false;
     }
 
+    @Override
+    public boolean onStartNestedScroll(View child, View target, int axes) {
+        if ((axes & SCROLL_AXIS_VERTICAL) == 0 || mActionBarTop.getVisibility() != VISIBLE) {
+            return false;
+        }
+        return mHideOnContentScroll;
+    }
+
+    @Override
+    public void onNestedScrollAccepted(View child, View target, int axes) {
+        super.onNestedScrollAccepted(child, target, axes);
+        mHideOnContentScrollReference = getActionBarHideOffset();
+        haltActionBarHideOffsetAnimations();
+        if (mActionBarVisibilityCallback != null) {
+            mActionBarVisibilityCallback.onContentScrollStarted();
+        }
+    }
+
+    @Override
+    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+            int dxUnconsumed, int dyUnconsumed) {
+        mHideOnContentScrollReference += dyConsumed;
+        setActionBarHideOffset(mHideOnContentScrollReference);
+    }
+
+    @Override
+    public void onStopNestedScroll(View target) {
+        super.onStopNestedScroll(target);
+        if (mHideOnContentScroll && !mAnimatingForFling) {
+            if (mHideOnContentScrollReference <= mActionBarTop.getHeight()) {
+                postRemoveActionBarHideOffset();
+            } else {
+                postAddActionBarHideOffset();
+            }
+        }
+        if (mActionBarVisibilityCallback != null) {
+            mActionBarVisibilityCallback.onContentScrollStopped();
+        }
+    }
+
+    @Override
+    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
+        if (!mHideOnContentScroll || !consumed) {
+            return false;
+        }
+        if (shouldHideActionBarOnFling(velocityX, velocityY)) {
+            addActionBarHideOffset();
+        } else {
+            removeActionBarHideOffset();
+        }
+        mAnimatingForFling = true;
+        return true;
+    }
+
     void pullChildren() {
         if (mContent == null) {
             mContent = findViewById(com.android.internal.R.id.content);
-            mActionBarTop = (ActionBarContainer)findViewById(
+            mActionBarTop = (ActionBarContainer) findViewById(
                     com.android.internal.R.id.action_bar_container);
             mActionBarView = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
             mActionBarBottom = findViewById(com.android.internal.R.id.split_action_bar);
         }
     }
 
+    public void setHideOnContentScrollEnabled(boolean hideOnContentScroll) {
+        if (hideOnContentScroll != mHideOnContentScroll) {
+            mHideOnContentScroll = hideOnContentScroll;
+            if (!hideOnContentScroll) {
+                stopNestedScroll();
+                haltActionBarHideOffsetAnimations();
+                setActionBarHideOffset(0);
+            }
+        }
+    }
+
+    public boolean isHideOnContentScrollEnabled() {
+        return mHideOnContentScroll;
+    }
+
+    public int getActionBarHideOffset() {
+        return mActionBarTop != null ? -((int) mActionBarTop.getTranslationY()) : 0;
+    }
+
+    public void setActionBarHideOffset(int offset) {
+        haltActionBarHideOffsetAnimations();
+        final int topHeight = mActionBarTop.getHeight();
+        offset = Math.max(0, Math.min(offset, topHeight));
+        mActionBarTop.setTranslationY(-offset);
+        if (mActionBarBottom != null && mActionBarBottom.getVisibility() != GONE) {
+            // Match the hide offset proportionally for a split bar
+            final float fOffset = (float) offset / topHeight;
+            final int bOffset = (int) (mActionBarBottom.getHeight() * fOffset);
+            mActionBarBottom.setTranslationY(bOffset);
+        }
+    }
+
+    private void haltActionBarHideOffsetAnimations() {
+        removeCallbacks(mRemoveActionBarHideOffset);
+        removeCallbacks(mAddActionBarHideOffset);
+        if (mCurrentActionBarTopAnimator != null) {
+            mCurrentActionBarTopAnimator.cancel();
+        }
+        if (mCurrentActionBarBottomAnimator != null) {
+            mCurrentActionBarBottomAnimator.cancel();
+        }
+    }
+
+    private void postRemoveActionBarHideOffset() {
+        haltActionBarHideOffsetAnimations();
+        postDelayed(mRemoveActionBarHideOffset, ACTION_BAR_ANIMATE_DELAY);
+    }
+
+    private void postAddActionBarHideOffset() {
+        haltActionBarHideOffsetAnimations();
+        postDelayed(mAddActionBarHideOffset, ACTION_BAR_ANIMATE_DELAY);
+    }
+
+    private void removeActionBarHideOffset() {
+        haltActionBarHideOffsetAnimations();
+        mRemoveActionBarHideOffset.run();
+    }
+
+    private void addActionBarHideOffset() {
+        haltActionBarHideOffsetAnimations();
+        mAddActionBarHideOffset.run();
+    }
+
+    private boolean shouldHideActionBarOnFling(float velocityX, float velocityY) {
+        mFlingEstimator.fling(0, 0, 0, (int) velocityY, 0, 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
+        final int finalY = mFlingEstimator.getFinalY();
+        return finalY > mActionBarTop.getHeight();
+    }
 
     public static class LayoutParams extends MarginLayoutParams {
         public LayoutParams(Context c, AttributeSet attrs) {
@@ -423,4 +646,13 @@
             super(source);
         }
     }
+
+    public interface ActionBarVisibilityCallback {
+        void onWindowVisibilityChanged(int visibility);
+        void showForSystem();
+        void hideForSystem();
+        void enableContentAnimations(boolean enable);
+        void onContentScrollStarted();
+        void onContentScrollStopped();
+    }
 }
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index 467d42e..674d084 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -35,7 +35,7 @@
 public class SwipeDismissLayout extends FrameLayout {
     private static final String TAG = "SwipeDismissLayout";
 
-    private static final float TRANSLATION_MIN_ALPHA = 0.5f;
+    private static final float DISMISS_MIN_PROGRESS = 0.6f;
 
     public interface OnDismissedListener {
         void onDismissed(SwipeDismissLayout layout);
@@ -77,6 +77,8 @@
     private OnDismissedListener mDismissedListener;
     private OnSwipeProgressChangedListener mProgressListener;
 
+    private float mLastX;
+
     public SwipeDismissLayout(Context context) {
         super(context);
         init(context);
@@ -95,7 +97,7 @@
     private void init(Context context) {
         ViewConfiguration vc = ViewConfiguration.get(getContext());
         mSlop = vc.getScaledTouchSlop();
-        mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * 16;
+        mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
         mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
         mAnimationTime = getContext().getResources().getInteger(
                 android.R.integer.config_shortAnimTime);
@@ -193,8 +195,8 @@
 
             case MotionEvent.ACTION_MOVE:
                 mVelocityTracker.addMovement(ev);
+                mLastX = ev.getRawX();
                 updateSwiping(ev);
-                updateDismiss(ev);
                 if (mSwiping) {
                     setProgress(ev.getRawX() - mDownX);
                     break;
@@ -256,20 +258,16 @@
             float absVelocityX = Math.abs(velocityX);
             float absVelocityY = Math.abs(mVelocityTracker.getYVelocity());
 
-            if (deltaX > getWidth() / 2) {
-                mDismissed = true;
-            } else if (absVelocityX >= mMinFlingVelocity
-                    && absVelocityX <= mMaxFlingVelocity
-                    && absVelocityY < absVelocityX / 2
-                    && velocityX > 0
-                    && deltaX > 0) {
+            if (deltaX > (getWidth() * DISMISS_MIN_PROGRESS) &&
+                    absVelocityX < mMinFlingVelocity && 
+                    ev.getRawX() >= mLastX) {
                 mDismissed = true;
             }
         }
         // Check if the user tried to undo this.
         if (mDismissed && mSwiping) {
             // Check if the user's finger is actually back
-            if (deltaX < getWidth() / 2) {
+            if (deltaX < (getWidth() * DISMISS_MIN_PROGRESS)) {
                 mDismissed = false;
             }
         }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index ee59c8a..667bf6c 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -92,6 +92,7 @@
 	android/graphics/BitmapFactory.cpp \
 	android/graphics/Camera.cpp \
 	android/graphics/Canvas.cpp \
+	android/graphics/CanvasProperty.cpp \
 	android/graphics/ColorFilter.cpp \
 	android/graphics/DrawFilter.cpp \
 	android/graphics/CreateJavaOutputStreamAdaptor.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f964cd2..66fbb8e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -105,6 +105,7 @@
 extern int register_android_content_XmlBlock(JNIEnv* env);
 extern int register_android_emoji_EmojiFactory(JNIEnv* env);
 extern int register_android_graphics_Canvas(JNIEnv* env);
+extern int register_android_graphics_CanvasProperty(JNIEnv* env);
 extern int register_android_graphics_ColorFilter(JNIEnv* env);
 extern int register_android_graphics_DrawFilter(JNIEnv* env);
 extern int register_android_graphics_Matrix(JNIEnv* env);
@@ -1221,6 +1222,7 @@
     REG_JNI(register_android_graphics_Camera),
     REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor),
     REG_JNI(register_android_graphics_Canvas),
+    REG_JNI(register_android_graphics_CanvasProperty),
     REG_JNI(register_android_graphics_ColorFilter),
     REG_JNI(register_android_graphics_DrawFilter),
     REG_JNI(register_android_graphics_Interpolator),
diff --git a/core/jni/android/graphics/CanvasProperty.cpp b/core/jni/android/graphics/CanvasProperty.cpp
new file mode 100644
index 0000000..70e2db5
--- /dev/null
+++ b/core/jni/android/graphics/CanvasProperty.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 20014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/VirtualLightRefBase.h>
+#include <CanvasProperty.h>
+
+namespace android {
+
+using namespace uirenderer;
+
+#ifdef USE_OPENGL_RENDERER
+
+static jlong incRef(VirtualLightRefBase* ptr) {
+    ptr->incStrong(0);
+    return reinterpret_cast<jlong>(ptr);
+}
+
+static jlong createFloat(JNIEnv* env, jobject clazz, jfloat initialValue) {
+    return incRef(new CanvasPropertyPrimitive(initialValue));
+}
+
+static jlong createPaint(JNIEnv* env, jobject clazz, jlong paintPtr) {
+    const SkPaint* paint = reinterpret_cast<const SkPaint*>(paintPtr);
+    return incRef(new CanvasPropertyPaint(*paint));
+}
+
+static void unref(JNIEnv* env, jobject clazz, jlong containerPtr) {
+    reinterpret_cast<VirtualLightRefBase*>(containerPtr)->decStrong(0);
+}
+
+#endif
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/graphics/CanvasProperty";
+
+static JNINativeMethod gMethods[] = {
+#ifdef USE_OPENGL_RENDERER
+    { "nCreateFloat", "(F)J", (void*) createFloat },
+    { "nCreatePaint", "(J)J", (void*) createPaint },
+    { "nUnref", "(J)V", (void*) unref },
+#endif
+};
+
+int register_android_graphics_CanvasProperty(JNIEnv* env) {
+    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp
index 799782d..6591d60 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.cpp
+++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp
@@ -226,16 +226,17 @@
     jint* imgOffsets = env->GetIntArrayElements(offsets, NULL);
     jint* imgStrides = env->GetIntArrayElements(strides, NULL);
     YuvToJpegEncoder* encoder = YuvToJpegEncoder::create(format, imgStrides);
-    if (encoder == NULL) {
-        return JNI_FALSE;
+    jboolean result = JNI_FALSE;
+    if (encoder != NULL) {
+        encoder->encode(strm, yuv, width, height, imgOffsets, jpegQuality);
+        delete encoder;
+        result = JNI_TRUE;
     }
-    encoder->encode(strm, yuv, width, height, imgOffsets, jpegQuality);
 
-    delete encoder;
     env->ReleaseByteArrayElements(inYuv, yuv, 0);
     env->ReleaseIntArrayElements(offsets, imgOffsets, 0);
     env->ReleaseIntArrayElements(strides, imgStrides, 0);
-    return JNI_TRUE;
+    return result;
 }
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 957f95c..05a99a3 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -18,8 +18,12 @@
 // #define LOG_NDEBUG 0
 // #define LOG_NNDEBUG 0
 #define LOG_TAG "CameraMetadata-JNI"
+#include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
 #include <string.h>
 
 #include "jni.h"
@@ -483,12 +487,20 @@
 
     ALOGV("%s (key = '%s')", __FUNCTION__, key);
 
+    sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
+
+    SortedVector<String8> vendorSections = vTags->getAllSectionNames();
+    size_t vendorSectionCount = vendorSections.size();
+
     // First, find the section by the longest string match
     const char *section = NULL;
     size_t sectionIndex = 0;
     size_t sectionLength = 0;
-    for (size_t i = 0; i < ANDROID_SECTION_COUNT; ++i) {
-        const char *str = camera_metadata_section_names[i];
+    size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
+    for (size_t i = 0; i < totalSectionCount; ++i) {
+
+        const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
+                vendorSections[i - ANDROID_SECTION_COUNT].string();
         ALOGVV("%s: Trying to match against section '%s'",
                __FUNCTION__, str);
         if (strstr(key, str) == key) { // key begins with the section name
@@ -502,12 +514,11 @@
                 sectionIndex = i;
                 sectionLength = strLength;
 
-                ALOGVV("%s: Found new best section (idx %d)", __FUNCTION__, sectionIndex);
+                ALOGVV("%s: Found new best section (%s)", __FUNCTION__, section);
             }
         }
     }
 
-    // TODO: vendor ext
     // TODO: Make above get_camera_metadata_section_from_name ?
 
     if (section == NULL) {
@@ -524,33 +535,47 @@
     if (sectionLength + 1 >= keyLength) {
         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                              "Key length too short for key '%s')", key);
+        return 0;
     }
 
     // Match rest of name against the tag names in that section only
-    uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
-    tagBegin = camera_metadata_section_bounds[sectionIndex][0];
-    tagEnd = camera_metadata_section_bounds[sectionIndex][1];
+    uint32_t tag = 0;
+    if (sectionIndex < ANDROID_SECTION_COUNT) {
+        // Match built-in tags (typically android.*)
+        uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
+        tagBegin = camera_metadata_section_bounds[sectionIndex][0];
+        tagEnd = camera_metadata_section_bounds[sectionIndex][1];
 
-    uint32_t tag;
-    for (tag = tagBegin; tag < tagEnd; ++tag) {
-        const char *tagName = get_camera_metadata_tag_name(tag);
+        for (tag = tagBegin; tag < tagEnd; ++tag) {
+            const char *tagName = get_camera_metadata_tag_name(tag);
 
-        if (strcmp(keyTagName, tagName) == 0) {
-            ALOGV("%s: Found matched tag '%s' (%d)",
-                  __FUNCTION__, tagName, tag);
-            break;
+            if (strcmp(keyTagName, tagName) == 0) {
+                ALOGV("%s: Found matched tag '%s' (%d)",
+                      __FUNCTION__, tagName, tag);
+                break;
+            }
+        }
+
+        if (tag == tagEnd) {
+            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                                 "Could not find tag name for key '%s')", key);
+            return 0;
+        }
+    } else {
+        // Match vendor tags (typically com.*)
+        const String8 sectionName(section);
+        const String8 tagName(keyTagName);
+
+        status_t res = OK;
+        if ((res = vTags->lookupTag(tagName, sectionName, &tag)) != OK) {
+            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                    "%s: No vendor tag matches key '%s'", __FUNCTION__, key);
+            return 0;
         }
     }
 
-    // TODO: vendor ext
     // TODO: Make above get_camera_metadata_tag_from_name ?
 
-    if (tag == tagEnd) {
-        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
-                             "Could not find tag name for key '%s')", key);
-        return 0;
-    }
-
     return tag;
 }
 
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index d8faaf3..09bdc61 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -393,13 +393,46 @@
                                                         jshortArray javaAudioData,
                                                         jint offsetInShorts, jint sizeInShorts) {
 
-    jint read = android_media_AudioRecord_readInByteArray(env, thiz,
-                                                        (jbyteArray) javaAudioData,
-                                                        offsetInShorts*2, sizeInShorts*2);
-    if (read > 0) {
-        read /= 2;
+    jshort* recordBuff = NULL;
+    // get the audio recorder from which we'll read new audio samples
+    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+    if (lpRecorder == NULL) {
+        ALOGE("Unable to retrieve AudioRecord object, can't record");
+        return 0;
     }
-    return read;
+
+    if (!javaAudioData) {
+        ALOGE("Invalid Java array to store recorded audio, can't record");
+        return 0;
+    }
+
+    // get the pointer to where we'll record the audio
+    // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
+    // a way that it becomes much more efficient. When doing so, we will have to prevent the
+    // AudioSystem callback to be called while in critical section (in case of media server
+    // process crash for instance)
+    recordBuff = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
+
+    if (recordBuff == NULL) {
+        ALOGE("Error retrieving destination for recorded audio data, can't record");
+        return 0;
+    }
+
+    // read the new audio data from the native AudioRecord object
+    const size_t recorderBuffSize = lpRecorder->frameCount()*lpRecorder->frameSize();
+    const size_t sizeInBytes = sizeInShorts * sizeof(short);
+    ssize_t readSize = lpRecorder->read(recordBuff + offsetInShorts * sizeof(short),
+                                        sizeInBytes > recorderBuffSize ?
+                                            recorderBuffSize : sizeInBytes);
+
+    env->ReleaseShortArrayElements(javaAudioData, recordBuff, 0);
+
+    if (readSize < 0) {
+        readSize = AUDIORECORD_ERROR_INVALID_OPERATION;
+    } else {
+        readSize /= sizeof(short);
+    }
+    return (jint) readSize;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 162d0c4..da752752 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -637,14 +637,43 @@
                                                   jshortArray javaAudioData,
                                                   jint offsetInShorts, jint sizeInShorts,
                                                   jint javaAudioFormat) {
-    jint written = android_media_AudioTrack_write_byte(env, thiz,
-                                                 (jbyteArray) javaAudioData,
-                                                 offsetInShorts*2, sizeInShorts*2,
-                                                 javaAudioFormat,
-                                                 JNI_TRUE /*blocking write, legacy behavior*/);
-    if (written > 0) {
-        written /= 2;
+
+    //ALOGV("android_media_AudioTrack_write_short(offset=%d, sizeInShorts=%d) called",
+    //    offsetInShorts, sizeInShorts);
+    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+    if (lpTrack == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+            "Unable to retrieve AudioTrack pointer for write()");
+        return 0;
     }
+
+    // get the pointer for the audio data from the java array
+    // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
+    // a way that it becomes much more efficient. When doing so, we will have to prevent the
+    // AudioSystem callback to be called while in critical section (in case of media server
+    // process crash for instance)
+    jshort* cAudioData = NULL;
+    if (javaAudioData) {
+        cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
+        if (cAudioData == NULL) {
+            ALOGE("Error retrieving source of audio data to play, can't play");
+            return 0; // out of memory or no data to load
+        }
+    } else {
+        ALOGE("NULL java array of audio data to play, can't play");
+        return 0;
+    }
+    jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
+                                offsetInShorts * sizeof(short), sizeInShorts * sizeof(short),
+            true /*blocking write, legacy behavior*/);
+    env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0);
+
+    if (written > 0) {
+        written /= sizeof(short);
+    }
+    //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d",
+    //     (int)written, (int)(sizeInShorts), (int)offsetInShorts);
+
     return written;
 }
 
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index ef5ebd0..3aa179d 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -49,6 +49,7 @@
 #include <Stencil.h>
 #include <Rect.h>
 #include <RenderNode.h>
+#include <CanvasProperty.h>
 
 #include <TextLayout.h>
 #include <TextLayoutCache.h>
@@ -544,6 +545,16 @@
     renderer->drawCircle(x, y, radius, paint);
 }
 
+static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
+        jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
+    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
+    CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
+    CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
+    CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
+    renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
+}
+
 static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jlong paintPtr) {
@@ -1041,6 +1052,7 @@
     { "nDrawRects",         "(J[FIJ)V",        (void*) android_view_GLES20Canvas_drawRects },
     { "nDrawRoundRect",     "(JFFFFFFJ)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
     { "nDrawCircle",        "(JFFFJ)V",        (void*) android_view_GLES20Canvas_drawCircle },
+    { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_GLES20Canvas_drawCircleProps },
     { "nDrawOval",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawOval },
     { "nDrawArc",           "(JFFFFFFZJ)V",    (void*) android_view_GLES20Canvas_drawArc },
     { "nDrawPoints",        "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawPoints },
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index 35cdf60..3be013b 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -16,8 +16,6 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
-#include "android_view_RenderNodeAnimator.h"
-
 #include "jni.h"
 #include "GraphicsJNI.h"
 #include <nativehelper/JNIHelp.h>
@@ -37,6 +35,8 @@
     jmethodID callOnFinished;
 } gRenderNodeAnimatorClassInfo;
 
+#ifdef USE_OPENGL_RENDERER
+
 static JNIEnv* getEnv(JavaVM* vm) {
     JNIEnv* env;
     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
@@ -45,46 +45,93 @@
     return env;
 }
 
-RenderNodeAnimator::RenderNodeAnimator(JNIEnv* env, jobject weakThis,
-                RenderProperty property, DeltaValueType deltaType, float delta)
-        : RenderPropertyAnimator(property, deltaType, delta) {
-    mWeakThis = env->NewGlobalRef(weakThis);
-    env->GetJavaVM(&mJvm);
-}
+class AnimationListenerBridge : public AnimationListener {
+public:
+    // This holds a strong reference to a Java WeakReference<T> object. This avoids
+    // cyclic-references-of-doom. If you think "I know, just use NewWeakGlobalRef!"
+    // then you end up with basically a PhantomReference, which is totally not
+    // what we want.
+    AnimationListenerBridge(JNIEnv* env, jobject weakThis) {
+        mWeakThis = env->NewGlobalRef(weakThis);
+        env->GetJavaVM(&mJvm);
+    }
 
-RenderNodeAnimator::~RenderNodeAnimator() {
-    JNIEnv* env = getEnv(mJvm);
-    env->DeleteGlobalRef(mWeakThis);
-    mWeakThis = NULL;
-}
+    virtual ~AnimationListenerBridge() {
+        JNIEnv* env = getEnv(mJvm);
+        env->DeleteGlobalRef(mWeakThis);
+        mWeakThis = NULL;
+    }
 
-void RenderNodeAnimator::callOnFinished() {
-    JNIEnv* env = getEnv(mJvm);
-    env->CallStaticVoidMethod(
-            gRenderNodeAnimatorClassInfo.clazz,
-            gRenderNodeAnimatorClassInfo.callOnFinished,
-            mWeakThis);
-}
+    virtual void onAnimationFinished(BaseAnimator*) {
+        JNIEnv* env = getEnv(mJvm);
+        env->CallStaticVoidMethod(
+                gRenderNodeAnimatorClassInfo.clazz,
+                gRenderNodeAnimatorClassInfo.callOnFinished,
+                mWeakThis);
+    }
 
-static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
-        jint property, jint deltaType, jfloat deltaValue) {
-    LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderNodeAnimator::ALPHA,
+private:
+    JavaVM* mJvm;
+    jobject mWeakThis;
+};
+
+static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint property) {
+    LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderPropertyAnimator::ALPHA,
             "Invalid property %d", property);
+    return static_cast<RenderPropertyAnimator::RenderProperty>(property);
+}
+
+static inline RenderPropertyAnimator::DeltaValueType toDeltaType(jint deltaType) {
     LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA
             && deltaType != RenderPropertyAnimator::ABSOLUTE,
             "Invalid delta type %d", deltaType);
+    return static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType);
+}
 
-    RenderNodeAnimator* animator = new RenderNodeAnimator(env, weakThis,
-            static_cast<RenderPropertyAnimator::RenderProperty>(property),
-            static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType),
-            deltaValue);
+static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) {
+    LOG_ALWAYS_FATAL_IF(field < 0
+            || field > CanvasPropertyPaintAnimator::ALPHA,
+            "Invalid paint field %d", field);
+    return static_cast<CanvasPropertyPaintAnimator::PaintField>(field);
+}
+
+static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
+        jint propertyRaw, jint deltaTypeRaw, jfloat deltaValue) {
+    RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw);
+    RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+
+    BaseAnimator* animator = new RenderPropertyAnimator(property, deltaType, deltaValue);
     animator->incStrong(0);
+    animator->setListener(new AnimationListenerBridge(env, weakThis));
+    return reinterpret_cast<jlong>( animator );
+}
+
+static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz,
+        jobject weakThis, jlong canvasPropertyPtr, jint deltaTypeRaw, jfloat deltaValue) {
+    RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+    CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr);
+    BaseAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, deltaType, deltaValue);
+    animator->incStrong(0);
+    animator->setListener(new AnimationListenerBridge(env, weakThis));
+    return reinterpret_cast<jlong>( animator );
+}
+
+static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz,
+        jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw,
+        jint deltaTypeRaw, jfloat deltaValue) {
+    RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+    CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr);
+    CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw);
+    BaseAnimator* animator = new CanvasPropertyPaintAnimator(
+            canvasProperty, paintField, deltaType, deltaValue);
+    animator->incStrong(0);
+    animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
 
 static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) {
     LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
-    RenderNodeAnimator* animator = reinterpret_cast<RenderNodeAnimator*>(animatorPtr);
+    BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
     animator->setDuration(duration);
 }
 
@@ -93,6 +140,8 @@
     obj->decStrong(0);
 }
 
+#endif
+
 // ----------------------------------------------------------------------------
 // JNI Glue
 // ----------------------------------------------------------------------------
@@ -100,9 +149,13 @@
 const char* const kClassPathName = "android/view/RenderNodeAnimator";
 
 static JNINativeMethod gMethods[] = {
+#ifdef USE_OPENGL_RENDERER
     { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator },
+    { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyFloatAnimator },
+    { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIIF)J", (void*) createCanvasPropertyPaintAnimator },
     { "nSetDuration", "(JI)V", (void*) setDuration },
     { "nUnref", "(J)V", (void*) unref },
+#endif
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/core/jni/android_view_RenderNodeAnimator.h b/core/jni/android_view_RenderNodeAnimator.h
deleted file mode 100644
index d84003f..0000000
--- a/core/jni/android_view_RenderNodeAnimator.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "jni.h"
-
-#include <Animator.h>
-
-namespace android {
-
-class RenderNodeAnimator : public uirenderer::RenderPropertyAnimator {
-public:
-    RenderNodeAnimator(JNIEnv* env, jobject callbackObject,
-            RenderProperty property, DeltaValueType deltaType, float delta);
-    virtual ~RenderNodeAnimator();
-
-    void callOnFinished();
-
-private:
-    JavaVM* mJvm;
-    jobject mWeakThis;
-};
-
-}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 58fc1e1..564c9a6 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -26,7 +26,7 @@
 #include <android_runtime/android_view_Surface.h>
 #include <system/window.h>
 
-#include "android_view_RenderNodeAnimator.h"
+#include <Animator.h>
 #include <RenderNode.h>
 #include <renderthread/RenderProxy.h>
 #include <renderthread/RenderTask.h>
@@ -67,26 +67,34 @@
     jobject mRunnable;
 };
 
+class OnFinishedEvent {
+public:
+    OnFinishedEvent(BaseAnimator* animator, AnimationListener* listener)
+            : animator(animator), listener(listener) {}
+    sp<BaseAnimator> animator;
+    sp<AnimationListener> listener;
+};
+
 class InvokeAnimationListeners : public MessageHandler {
 public:
-    InvokeAnimationListeners(std::vector< sp<RenderNodeAnimator> >& animators) {
-        mAnimators.swap(animators);
+    InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
+        mOnFinishedEvents.swap(events);
     }
 
-    static void callOnFinished(const sp<RenderNodeAnimator>& animator) {
-        animator->callOnFinished();
+    static void callOnFinished(OnFinishedEvent& event) {
+        event.listener->onAnimationFinished(event.animator.get());
     }
 
     virtual void handleMessage(const Message& message) {
-        std::for_each(mAnimators.begin(), mAnimators.end(), callOnFinished);
-        mAnimators.clear();
+        std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
+        mOnFinishedEvents.clear();
     }
 
 private:
-    std::vector< sp<RenderNodeAnimator> > mAnimators;
+    std::vector<OnFinishedEvent> mOnFinishedEvents;
 };
 
-class RootRenderNode : public RenderNode, public AnimationListener {
+class RootRenderNode : public RenderNode, public AnimationHook {
 public:
     RootRenderNode() : RenderNode() {
         mLooper = Looper::getForThread();
@@ -96,27 +104,27 @@
 
     virtual ~RootRenderNode() {}
 
-    void onAnimationFinished(const sp<RenderPropertyAnimator>& animator) {
-        mFinishedAnimators.push_back(
-                reinterpret_cast<RenderNodeAnimator*>(animator.get()));
+    virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) {
+        OnFinishedEvent event(animator, listener);
+        mOnFinishedEvents.push_back(event);
     }
 
     virtual void prepareTree(TreeInfo& info) {
-        info.animationListener = this;
+        info.animationHook = this;
         RenderNode::prepareTree(info);
-        info.animationListener = NULL;
+        info.animationHook = NULL;
 
         // post all the finished stuff
-        if (mFinishedAnimators.size()) {
+        if (mOnFinishedEvents.size()) {
             sp<InvokeAnimationListeners> message
-                    = new InvokeAnimationListeners(mFinishedAnimators);
+                    = new InvokeAnimationListeners(mOnFinishedEvents);
             mLooper->sendMessage(message, 0);
         }
     }
 
 private:
     sp<Looper> mLooper;
-    std::vector< sp<RenderNodeAnimator> > mFinishedAnimators;
+    std::vector<OnFinishedEvent> mOnFinishedEvents;
 };
 
 static void android_view_ThreadedRenderer_postToRenderThread(JNIEnv* env, jobject clazz,
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index a61fa87..c58bf04 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -92,14 +92,10 @@
     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));
+        ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
       }
 #ifdef WCOREDUMP
       if (WCOREDUMP(status)) {
@@ -117,8 +113,10 @@
     }
   }
 
-  if (pid < 0) {
-    ALOGW("Zygote SIGCHLD error in waitpid: %d", errno);
+  // Note that we shouldn't consider ECHILD an error because
+  // the secondary zygote might have no children left to wait for.
+  if (pid < 0 && errno != ECHILD) {
+    ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno));
   }
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4f093a8..241500a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1279,7 +1279,7 @@
          or recently running tasks. -->
     <permission android:name="android.permission.GET_TASKS"
         android:permissionGroup="android.permission-group.APP_INFO"
-        android:protectionLevel="dangerous"
+        android:protectionLevel="signature|system"
         android:label="@string/permlab_getTasks"
         android:description="@string/permdesc_getTasks" />
     <!-- @hide Allows an application to call APIs that allow it to do interactions
@@ -2681,6 +2681,26 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
+        <activity android:name="com.android.internal.app.IntentForwarderActivity"
+                android:finishOnCloseSystemDialogs="true"
+                android:theme="@style/Theme.NoDisplay"
+                android:excludeFromRecents="true"
+                android:label="@string/user_owner_label"
+                android:exported="true"
+                >
+        </activity>
+        <activity-alias android:name="com.android.internal.app.ForwardIntentToUserOwner"
+                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                android:icon="@drawable/personal_icon"
+                android:exported="true"
+                android:label="@string/user_owner_label">
+        </activity-alias>
+        <activity-alias android:name="com.android.internal.app.ForwardIntentToManagedProfile"
+                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                android:icon="@drawable/work_icon"
+                android:exported="true"
+                android:label="@string/managed_profile_label">
+        </activity-alias>
         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
                 android:theme="@style/Theme.Holo.Dialog"
                 android:label="@string/heavy_weight_switcher_title"
@@ -2773,7 +2793,7 @@
 
         <receiver android:name="com.android.server.BootReceiver"
                 android:primaryUserOnly="true">
-            <intent-filter>
+            <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
diff --git a/core/res/res/drawable-hdpi/personal_icon.png b/core/res/res/drawable-hdpi/personal_icon.png
new file mode 100644
index 0000000..8d96b5e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/personal_icon.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/work_icon.png b/core/res/res/drawable-hdpi/work_icon.png
new file mode 100644
index 0000000..e90866b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/work_icon.png
Binary files differ
diff --git a/core/res/res/layout/alert_dialog_micro.xml b/core/res/res/layout/alert_dialog_micro.xml
new file mode 100644
index 0000000..f8eb46c
--- /dev/null
+++ b/core/res/res/layout/alert_dialog_micro.xml
@@ -0,0 +1,138 @@
+<?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="match_parent"
+    android:orientation="vertical">
+
+    <LinearLayout android:id="@+id/topPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <View android:id="@+id/titleDividerTop"
+            android:layout_width="match_parent"
+            android:layout_height="2dip"
+            android:visibility="gone"
+            android:background="@android:color/holo_blue_light" />
+        <LinearLayout android:id="@+id/title_template"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:gravity="center_vertical|start"
+            android:minHeight="@dimen/alert_dialog_title_height"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip">
+            <ImageView android:id="@+id/icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingEnd="8dip"
+                android:src="@null" />
+            <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
+                style="?android:attr/windowTitleStyle"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="viewStart" />
+        </LinearLayout>
+        <View android:id="@+id/titleDivider"
+            android:layout_width="match_parent"
+            android:layout_height="2dip"
+            android:visibility="gone"
+            android:background="@android:color/holo_blue_light" />
+        <!-- If the client uses a customTitle, it will be added here. -->
+    </LinearLayout>
+
+    <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="8dip"
+                android:paddingBottom="8dip"/>
+        </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:divider="?android:attr/dividerHorizontal"
+        android:showDividers="beginning"
+        android:dividerPadding="0dip">
+        <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/button2"
+                android:layout_width="wrap_content"
+                android:layout_gravity="start"
+                android:layout_weight="1"
+                android:maxLines="2"
+                style="?android:attr/buttonBarButtonStyle"
+                android:textSize="14sp"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                android:layout_height="wrap_content" />
+            <Button android:id="@+id/button3"
+                android:layout_width="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_weight="1"
+                android:maxLines="2"
+                style="?android:attr/buttonBarButtonStyle"
+                android:textSize="14sp"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                android:layout_height="wrap_content" />
+            <Button android:id="@+id/button1"
+                android:layout_width="wrap_content"
+                android:layout_gravity="end"
+                android:layout_weight="1"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                style="?android:attr/buttonBarButtonStyle"
+                android:textSize="14sp"
+                android:layout_height="wrap_content" />
+        </LinearLayout>
+     </LinearLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/voice_interaction_session.xml b/core/res/res/layout/voice_interaction_session.xml
new file mode 100644
index 0000000..48b6579
--- /dev/null
+++ b/core/res/res/layout/voice_interaction_session.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/layout/alert_dialog.xml
+**
+** Copyright 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:id="@android:id/content"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+</FrameLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index eb68c39..20d306d 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="UNIT">%2$s</xliff:g><xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Titelloos&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n VPN-diens te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind aan \'n muurpapier"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n muurpapier te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"verbind met \'n steminteraksiediens"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Laat die houer toe om met die topvlak-koppelvlak van \'n steminteraksiediens te verbind. Behoort nooit vir normale programme nodig te wees nie."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"koppel aan \'n afstandskerm"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Dit laat die houer toe om aan die top-koppelvlak van \'n afstandskerm te koppel. Behoort nooit vir gewone programme nodig te wees nie."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind aan \'n legstukdiens"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Laat die program toe om kennisgewings op te haal, te bestudeer en te verwyder, insluitende die kennisgewings wat deur ander programme geplaas is."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bind aan \'n kennisgewingluisteraardiens"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Laat die houer toe om aan die top-koppelvlak van \'n kennisgewingluisteraardiens te bind. Behoort nooit vir gewone programme nodig te wees nie."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"verbind met \'n toestandverskafferdiens"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Laat die houer toe om met die topvlak-koppelvlak van \'n toestandverskafferdiens te verbind. Behoort nooit vir normale programme nodig te wees nie."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"roep die opstellingprogram op wat deur die diensverskaffer voorsien is"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Laat die houer toe om die opstellingsprogram wat deur die diensverskaffer voorsien word, op te roep. Behoort nooit vir gewone programme nodig te wees nie."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"luister vir waarnemings oor netwerktoestande"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Muurpapier"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Verander muurpapier"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Kennisgewingluisteraar"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Toestandverskaffer"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN geaktiveer"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is geaktiveer deur <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak om die netwerk te bestuur."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 05594b3..04bfee5 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;ርዕስ አልባ&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"የVPN ግልጋሎትን ወደ ከፍተኛ-ደረጃ በየነ ገጽ ለማሳር ለመያዣው ይፈቅዳሉ፡፡ለተለመዱ መተግበሪያዎች አያስፈልግም፡፡"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"በልጣፍ ጠርዝ"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"ያዡ ግቤት ስልቱን ወደ ከፍተኛ-ደረጃ ልጣፍ ለመጠረዝ ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"ከአንድ የድምጽ በይነተገናኝ ጋር ይሰሩ"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"ያዢው የአንድ የድምጽ በይነግንኙነት አገልግሎት የከፍተኛ ደረጃ በይነገጽ እንዲያስር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ከአንድ የርቀት ማሳያ ጋር ይጠርዛል"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"ያዢው ከአንድ የርቀት ማሳያ ከፍተኛ-ደረጃ በይነገጽ ጋር እንዲጠርዝ ይፈቅድለታል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ወደ ፍርግም አገልግሎት አያይዝ"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"መተግበሪያው ማሳወቂያዎችን እንዲያስመጣ፣ እንዲመረምር እና እንዲያጸዳ ያስችለዋል፣ በሌሎች መተግበሪያዎች የተለጠፉትንም ጨምሮ።"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ከአንድ የማሳወቂያ አዳማጭ አገልግሎት ጋር ይሰሩ"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ያዢው የማሳወቂያ አዳማጭ አገልግሎቱን ከከፍተኛ-ደረጃ በይነገጹ ጋር እንዲያስር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ከአንድ የሁኔታ አቅራቢ አገልግሎት ጋር ይሰሩ"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"ያዢው የአንድ የሁኔታ አቅራቢ አገልግሎት የከፍተኛ ደረጃ በይነገጽ እንዲያስር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"በድምጸ-ተያያዥ ሞደም የቀረበው የውቅር መተግበሪያውን መጥራት"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ያዢው በድምጸ-ተያያዥ ሞደም የቀረበው የውቅር መተግበሪያውን እንዲጠራው ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"በአውታረ መረብ ሁኔታዎች ላይ የተስተዋሉ ነገሮችን ያዳምጣል"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ልጣፍ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ልጣፍ ለውጥ"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ማሳወቂያ አዳማጭ"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"የሁኔታ አቅራቢ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ነቅቷል።"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN በ<xliff:g id="APP">%s</xliff:g>ገብሯል"</string>
     <string name="vpn_text" msgid="3011306607126450322">"አውታረመረብ ለማደራጀት  ንካ።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index fa662fd..83168e4 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"تيرابايت"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"بيتابايت"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"‏&lt;بلا عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"‏للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة الشبكة الظاهرية الخاصة (VPN). لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"الالتزام بخلفية ما"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"للسماح للمالك بالالتزام بواجهة المستوى العلوي للخلفية. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"الربط بخدمة التفاعل الصوتي"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"للسماح للمالك بالربط بواجهة المستوى العلوي لخدمة التفاعل الصوتي. لن تكون هناك حاجة إلى هذا الإعداد مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"الربط بالشاشة عن بُعد"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"للسماح للمالك بالالتزام بواجهة المستوى العلوي للعرض عن بُعد. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"الالتزام بخدمة أداة"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"يتيح للتطبيق استرجاع الإشعارات وفحصها ومسحها، بما في ذلك تلك التي نشرتها تطبيقات أخرى."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"الربط بخدمة تلقّي الإشعارات الصوتية"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"يتيح للمالك الربط بواجهة المستوى العلوي لخدمة تلقّي الإشعارات الصوتية. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"الربط بخدمة موفر الحالة"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"للسماح للمالك بالربط بواجهة المستوى العلوي لخدمة موفر الحالة. لن تكون هناك حاجة إلى هذا الإعداد مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"استدعاء تطبيق التهيئة الذي يوفره مشغل شبكة الجوال"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"للسماح للمالك باستدعاء تطبيق التهيئة الذي يوفره مشغل شبكة الجوال. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"الاستماع إلى ملاحظات حول أحوال الشبكة"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"الخلفية"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغيير الخلفية"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"برنامج تلقّي الإشعارات الصوتية"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"موفر الحالة"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏تم تنشيط الشبكة الظاهرية الخاصة (VPN)"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏تم تنشيط VPN بواسطة <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"المس لإدارة الشبكة."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index d347db6..2d22cdc 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Без заглавие&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на услуга за VPN. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"обвързване с тапет"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на тапет. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"свързване с услуга за гласово взаимодействие"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Разрешава на притежателя да се свърже с интерфейса от най-високото ниво на услуга за гласово взаимодействие. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"свързване с отдалечен екран"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Разрешава на притежателя да се свърже с интерфейса от първо ниво на отдалечен екран. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обвързване с услуга за приспособления"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Разрешава на приложението да извлича, преглежда и изчиства известия, включително публикуваните от други приложения."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"обвързване с услуга за слушател на известия"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Разрешава на притежателя да се обвърже с интерфейса от първо ниво на услуга за слушател на известия. Нормалните приложения не би трябвало никога да се нуждаят от това."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"свързване с услуга за предоставяне на условия"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Разрешава на притежателя да се свърже с интерфейса от най-високото ниво на услуга за предоставяне на условия. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"извикване на предоставеното от оператора приложение за конфигуриране"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Разрешава на притежателя да извиква предоставеното от оператора приложение за конфигуриране. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"слушане за наблюдения на мрежовите условия"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промяна на тапета"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Слушател на известия"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Доставчик на условия"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN е активирана"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана от <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Докоснете за управление на мрежата."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index fce2c4e..cfb77d3 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sense títol&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de VPN. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"enllaça amb un fons de pantalla"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet que el titular vinculi a la interfície de nivell superior d\'un fons de pantalla. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"vinculació amb una eina d\'interacció de veu"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permet que el titular es vinculi amb la interfície de nivell superior d\'un servei d\'interacció de veu. No ha de ser mai necessari per a aplicacions normals."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vincula a una pantalla remota"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permet que el titular es vinculi a la interfície de nivell superior d\'una pantalla remota. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincula a un servei de widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet que l\'aplicació recuperi, examini i esborri les notificacions, incloses les que han publicat altres aplicacions."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincula a un servei oient de notificacions"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet que el titular vinculi la interfície de nivell superior d\'un servei oient de notificacions. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"vinculació amb el servei d\'un proveïdor de condicions"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet que el titular es vinculi amb la interfície de nivell superior del servei d\'un proveïdor de condicions. No ha de ser mai necessari per a aplicacions normals."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoca l\'aplicació de configuració proporcionada per l\'operador"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet que el titular invoqui l\'aplicació de configuració proporcionada per l\'operador. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"conèixer les observacions sobre les condicions de la xarxa"</string>
@@ -717,14 +735,14 @@
     <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permet que una aplicació proporcioni i utilitzi certificats de gestió de drets digitals (DRM, Digital Rights Management). No ha de ser mai necessari per a aplicacions normals."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
-    <string name="policylab_watchLogin" msgid="914130646942199503">"Controlar intents de desbloqueig de pantalla"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Controlar els intents de desbloqueig de pantalla"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el telèfon o esborra totes les dades del telèfon si s\'introdueixen massa contrasenyes incorrectes."</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"Canvia la contrasenya de desbloqueig de pantalla"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"Canvia la contrasenya de desbloqueig de pantalla."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Bloqueig de pantalla"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"Controla com i quan es bloqueja la pantalla."</string>
-    <string name="policylab_wipeData" msgid="3910545446758639713">"Esborra totes les dades"</string>
+    <string name="policylab_wipeData" msgid="3910545446758639713">"Esborrar totes les dades"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Esborra les dades de la tauleta sense advertiment mitjançant un restabliment de les dades de fàbrica."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Esborra les dades del telèfon sense avisar, restablint les dades de fàbrica."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Defineix el servidor intermediari global del dispositiu"</string>
@@ -734,7 +752,7 @@
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptació d’emmagatzematge"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Requereix que les dades de l\'aplicació emmagatzemades estiguin encriptades."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Desactivar les càmeres"</string>
-    <string name="policydesc_disableCamera" msgid="2306349042834754597">"Impedeix l\'ús de totes les càmeres del dispositiu."</string>
+    <string name="policydesc_disableCamera" msgid="2306349042834754597">"Impedeix l\'ús de les càmeres del dispositiu."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Des. funcions en bloq. tecles"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Impedeix l\'ús d\'algunes funcions en bloqueig de tecles."</string>
   <string-array name="phoneTypes">
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fons de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvia el fons de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Oient de notificacions"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveïdor de condicions"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca per gestionar la xarxa."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 2f73544..868f899 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez názvu&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Umožňuje držiteli navázat se na nejvyšší úroveň služby VPN. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vazba na tapetu"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní tapety. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"navázání na hlasovou interakci"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní služby hlasové interakce. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"připojit se ke vzdálenému displeji"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Umožňuje držiteli připojit se k vysokoúrovňovému rozhraní vzdáleného displeje. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"navázat se na službu widgetu"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikacím načítat, zobrazovat a mazat oznámení včetně těch přidaných jinými aplikacemi."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"navázání na službu pro poslouchání oznámení"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Umožňuje držiteli navázat se na nejvyšší úroveň služby pro poslouchání oznámení. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"navázání na službu poskytovatele podmínky"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní služby poskytovatele podmínky. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"vyvolat konfigurační aplikaci poskytnutou operátorem"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Umožňuje vyvolání konfigurační aplikace poskytnuté operátorem. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"naslouchat informacím o stavu sítě"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Změnit tapetu"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Aplikace poslouchající oznámení"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Poskytovatel podmínky"</string>
     <string name="vpn_title" msgid="19615213552042827">"Síť VPN je aktivována"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikace <xliff:g id="APP">%s</xliff:g> aktivovala síť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykem zobrazíte správu sítě."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d1ab769..206db12 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"Tb"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Pb"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Uden titel&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Tillader, at brugeren forpligter sig til en VPN-tjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt i almindelige apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"knyt til en baggrund"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Tillader, at indehaveren kan binde en baggrunds grænseflade på øverste niveau. Dette bør aldrig være nødvendigt for almindelige apps."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"oprette binding til en tjeneste til stemmeinteraktion"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Tillader, at brugeren opretter en binding til det øverste niveau af grænsefladen i en tjeneste til stemmeinteraktion. Dette bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind til en ekstern skærm"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Tillader, at brugeren kan foretage en binding til grænsefladens øverste niveau på en ekstern skærm. Bør aldrig være nødvendigt til almindelige apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"forpligt til en widgettjeneste"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillader, at appen kan hente, undersøge og rydde underretninger, f.eks. dem, der er sendt af andre apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"forpligte sig til en underretningslyttertjeneste"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Tillader brugeren at forpligte sig til en underretningslyttertjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"oprette binding til en tjeneste til formidling af betingelser"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Tillader, at brugeren opretter en binding til det øverste niveau af grænsefladen i en tjeneste til formidling af betingelser. Dette bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"aktivere konfigurationsappen, der leveres af mobilselskabet"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Tillader, at brugeren aktiverer konfigurationsappen, der er forsynet af mobilselskabet. Dette bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"observer netværksforhold"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Baggrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift baggrund"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Underretningslytter"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Tjeneste til formidling af betingelser"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktiveret."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveres af <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryk for at administrere netværket."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 31b9c9d..87d4aa0 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Unbenannt&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Ermöglicht dem Halter, sich an die Oberfläche eines VPN-Dienstes auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"An einen Hintergrund binden"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Ermöglicht dem Halter, sich an die Oberfläche eines Hintergrunds auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"An einen Sprachinteraktionsdienst binden"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Ermöglicht dem Inhaber, sich an die Oberfläche eines Sprachinteraktionsdienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"An Remote-Display binden"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ermöglicht dem Halter, sich an die Oberfläche eines Remote-Displays auf oberster Ebene zu binden. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"An einen Widget-Dienst binden"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ermöglicht der App das Abrufen, Überprüfen und Löschen von Benachrichtigungen, einschließlich Benachrichtigungen, die von anderen Apps gepostet wurden"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"An Benachrichtigungs-Listener-Dienst binden"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ermöglicht dem Inhaber, sich an die Oberfläche der obersten Ebene eines Benachrichtigungs-Listener-Dienstes zu binden. Sollte nie für normale Apps benötigt werden."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"An einen Bedingungsanbieterdienst binden"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ermöglicht dem Inhaber, sich an die Oberfläche eines Bedingungsanbieterdienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufrufen"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ermöglicht dem Inhaber, die vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufzurufen. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Informationen zu den Netzwerkbedingungen erfassen"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hintergrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Hintergrund ändern"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Benachrichtigungs-Listener"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Bedingungsanbieter"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wurde von <xliff:g id="APP">%s</xliff:g> aktiviert."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Zum Verwalten des Netzwerks berühren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index a1d6049..9105cb2 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Χωρίς τίτλο&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας Vpn. Δεν απαιτείται για κανονικές εφαρμογές."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"δέσμευση σε ταπετσαρία"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας ταπετσαρίας. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"σύνδεση σε παράγοντα φωνητικής αλληλεπίδρασης"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Επιτρέπει στον κάτοχο τη σύνδεση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας φωνητικής αλληλεπίδρασης. Δεν απαιτείται για κανονικές εφαρμογές."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"μεταφορά σε μια απομακρυσμένη οθόνη"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας απομακρυσμένης οθόνης. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"δέσμευση σε υπηρεσία γραφικών στοιχείων"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Επιτρέπει στην εφαρμογή να ανακτά, να εξετάζει και να απαλείφει ειδοποιήσεις, συμπεριλαμβανομένων εκείνων που δημοσιεύονται από άλλες εφαρμογές."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"δέσμευση σε υπηρεσία ακρόασης ειδοποίησης"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας ακρόασης ειδοποιήσεων. Δεν απαιτείται σε κανονικές εφαρμογές."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"σύνδεση σε μια υπηρεσία παρόχου συνθηκών"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Επιτρέπει στον κάτοχο τη σύνδεση στη διεπαφή ανωτάτου επιπέδου ενός παρόχου συνθηκών. Δεν απαιτείται για κανονικές εφαρμογές."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"κλήση της εφαρμογής διαμόρφωσης που παρέχεται από την εταιρεία κινητής τηλεφωνίας"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Επιτρέπει στον κάτοχο την κλήση της εφαρμογής διαμόρφωσης που παρέχεται από την εταιρεία κινητής τηλεφωνίας. Δεν απαιτείται για κανονικές εφαρμογές."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"λήψη παρατηρήσεων σχετικά με την κατάσταση δικτύου"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ταπετσαρία"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Αλλαγή ταπετσαρίας"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Υπηρεσία ακρόασης ειδοποίησης"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Πάροχος συνθηκών"</string>
     <string name="vpn_title" msgid="19615213552042827">"Το VPN ενεργοποιήθηκε"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Το VPN ενεργοποιήθηκε από την εφαρμογή <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Αγγίξτε για τη διαχείριση του δικτύου."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 33f0010..51a85e3 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Untitled&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Allows the holder to bind to the top-level interface of a Vpn service. Should never be needed for normal apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind to wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"bind to a voice interactor"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Allows the holder to bind to the top-level interface of a voice interaction service. Should never be needed for normal apps."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind to a remote display"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Allows the holder to bind to the top-level interface of a remote display. Should never be needed for normal apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Allows the app to retrieve, examine, and clear notifications, including those posted by other apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bind to a notification listener service"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bind to a condition provider service"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoke the carrier-provided configuration app"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"listen for observations on network conditions"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 33f0010..51a85e3 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Untitled&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Allows the holder to bind to the top-level interface of a Vpn service. Should never be needed for normal apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind to wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"bind to a voice interactor"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Allows the holder to bind to the top-level interface of a voice interaction service. Should never be needed for normal apps."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind to a remote display"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Allows the holder to bind to the top-level interface of a remote display. Should never be needed for normal apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Allows the app to retrieve, examine, and clear notifications, including those posted by other apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bind to a notification listener service"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bind to a condition provider service"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoke the carrier-provided configuration app"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"listen for observations on network conditions"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 620d745..2a4f7e9 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sin título&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite al titular vincularse a la interfaz de nivel superior de un servicio de VPN. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a un fondo de pantalla"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite al propietario vincularse a la interfaz de nivel superior de un fondo de pantalla. Las aplicaciones normales no deben utilizar este permiso."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"vincular con un servicio de interacción por voz"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite vincular con la interfaz de nivel superior de un servicio de interacción por voz. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vincular a una pantalla remota"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite al propietario vincularse a la interfaz de nivel superior de una pantalla remota. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a un servicio de widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y elimine notificaciones, incluidas aquellas publicadas por otras aplicaciones."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"Vincular a un servicio de agente de escucha de notificaciones"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite al propietario vincularse a la interfaz de nivel superior de un servicio de agente de escucha de notificaciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"vincular con un servicio de proveedor de condiciones"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite vincular con la interfaz de nivel superior de un servicio de proveedor de condiciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ejecutar la aplicación de configuración proporcionada por el proveedor"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite al propietario ejecutar la aplicación de configuración proporcionada por el proveedor. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Detectar cambios en el estado de la red"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Papel tapiz"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Agente de escucha de notificaciones"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveedor de condiciones"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN está activado por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index cd96a08..2e0d68b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sin título&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite enlazar con la interfaz de nivel superior de un servicio de VPN. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"enlazar con un fondo de pantalla"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite enlazar con la interfaz de nivel superior de un fondo de pantalla. Las aplicaciones normales no deberían necesitar este permiso."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"enlazar con un servicio de interacción de voz"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite enlazar con la interfaz de nivel superior de un servicio de interacción de voz. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"enlazar a una pantalla remota"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite enlazar con la interfaz de nivel superior de una pantalla remota. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"enlazar con un servicio de widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y borre notificaciones, incluidas las que han publicado otras aplicaciones."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"enlazar con un servicio de detector de notificaciones"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite enlazar con la interfaz de nivel superior de un servicio de detector de notificaciones. No debe ser necesario para las aplicaciones normales."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"enlazar con un servicio de proveedor de condiciones"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite enlazar con la interfaz de nivel superior de un servicio de proveedor de condiciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ejecutar la aplicación de configuración proporcionada por el operador"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite ejecutar la aplicación de configuración proporcionada por el operador. No debe ser necesario para aplicaciones normales."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"detectar cambios en el estado de la red"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Detector de notificaciones"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveedor de condiciones"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 1d905df..32abeb8 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Pealkirjata&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥."</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Võimaldab omanikul siduda VPN-teenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"taustapildiga sidumine"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lubab omanikul siduda taustapildi ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"seo häälinteraktsiooniga"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Lubab omanikul siduda häälinteraktsiooni teenuse ülataseme liidesega. Pole kunagi vajalik tavaliste rakenduste puhul."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"kaugekraaniga sidumine"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lubab omanikul siduda rakenduse kaugekraani ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vidinateenusega sidumine"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Võimaldab rakendusel tuua, kontrollida ja kustutada märguandeid, sh neid, mille on postitanud teised rakendused."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"seo märguannete kuulamisteenusega"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Võimaldab omanikul siduda märguannete kuulamisteenuse ülemise taseme kasutajaliidese. Seda ei tohiks tavarakenduste puhul kunagi vaja olla."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"seo tingimuse pakkuja teenusega"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Lubab omanikul siduda tingimuse pakkuja teenuse ülataseme liidesega. Pole kunagi vajalik tavaliste rakenduste puhul."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"operaatoripoolse konfiguratsioonirakenduse aktiveerimine"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lubab omanikul aktiveerida operaatoripoolse konfiguratsioonirakenduse. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"võrgutingimuste teabe kuulamine"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustapilt"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Muutke taustapilti"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Märguannete kuulamisteenus"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Tingimuse pakkuja"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktiveeritud"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-i aktiveeris <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Võrgu haldamiseks puudutage."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index a198fbb..c5abcbd 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"ترابایت"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"پتابایت"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"‏&lt;بدون عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"‏به دارنده اجازه می‌دهد که به رابط سطح بالای سرویس Vpn متصل شود. هرگز برای برنامه‌های معمولی مورد نیاز نیست."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"پیوند شده به تصویر زمینه"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"‏به دارنده اجازه می‎دهد تا به رابط سطح بالای تصویر زمینه متصل شود. برنامه‎های معمولی هرگز به این ویژگی نیاز ندارند."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"مقید بودن به سرویس تعامل صوتی"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"به دارنده امکان می‌دهد به واسط سطح بالای سرویس تعامل صوتی مقید باشد. برای برنامه‌های عادی هرگز نباید لازم باشد."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"اتصال به نمایشگر راه دور"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"به دارنده ام‍ک‍ان می‌دهد تا به رابط سطح بالای نمایشگر راه دور وصل شود. نباید هرگز برای برنامه‌های عادی لازم باشد."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"اتصال به یک سرویس ابزارک"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"به برنامه اجازه می‌دهد به بازیابی، بررسی و پاک کردن اعلان‌ها از جمله موارد پست شده توسط سایر برنامه‌ها بپردازد."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"اتصال به یک سرویس شنونده اعلان"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"به دارنده اجازه می‌دهد به یک رابط سطح بالای سرویس شنونده اعلان متصل شود. هرگز نباید برای برنامه‌های عادی لازم شود."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"مقید بودن به سرویس ارائه‌دهنده وضعیت"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"به دارنده امکان می‌دهد تا به واسط سطح بالای سرویس ارائه‌دهنده وضعیت مقید باشد. برای برنامه‌های عادی هرگز نباید لازم باشد."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"لغو برنامه پیکربندی ارائه شده توسط شرکت مخابراتی"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"به دارنده اجازه می‌دهد که تنظیمات برنامه شرکت مخابراتی را لغو کند. هرگز برای برنامه‌های معمولی مورد نیاز نیست."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"گوش دادن برای بررسی شرایط شبکه"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"تصویر زمینه"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغییر تصویر زمینه"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"شنونده اعلان"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ارائه‌دهنده وضعیت"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN فعال شد"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏VPN توسط <xliff:g id="APP">%s</xliff:g> فعال شده است"</string>
     <string name="vpn_text" msgid="3011306607126450322">"برای مدیریت شبکه لمس کنید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 5a01910..945c7ab 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"Tt"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Pt"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Nimetön&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 17cda8d..c917749 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"To"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Po"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sans_titre&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service RPV. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"se fixer à un fond d\'écran"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un fond d\'écran. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"s\'associer à un service d\'interaction vocale"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'interaction vocale. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"lier à un écran distant"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un écran distant. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"s\'associer à un service de widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet aux applications de récupérer, d\'examiner et d\'autoriser les notifications, y compris celles envoyées par d\'autres applications."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications. Ne devrait jamais être nécessaire pour les applications normales."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"s\'associer à un service de fournisseur de conditions"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service de fournisseur de conditions. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"faire appel à l\'application de configuration du fournisseur de services"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet à l\'application autorisée de faire appel à l\'application de configuration fournie par le fournisseur de services. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"détecter des observations sur les conditions du réseau"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Outil d\'écoute des notifications"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 3c0266f..9359606 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"To"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Po"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sans nom&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service VPN. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"Se fixer sur un fond d\'écran"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un fond d\'écran. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"s\'associer à un service d\'interaction vocale"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'interaction vocale. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"s\'associer à un écran à distance"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permettre à l\'application autorisée de s\'associer à l\'interface de niveau supérieur d\'un écran à distance. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associer à un service widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet aux applications de récupérer, d\'examiner et d\'autoriser les notifications, y compris celles envoyées par d\'autres applications."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications. Ne devrait jamais être nécessaire pour les applications normales."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"s\'associer à un service de fournisseur de conditions"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service de fournisseur de conditions. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"faire appel à l\'application de configuration fournie par l\'opérateur"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet à l\'application autorisée de faire appel à l\'application de configuration fournie par l\'opérateur. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"détecter des observations sur les conditions du réseau"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Outil d\'écoute des notifications"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1638b6bc..3d5f4df 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;शीर्षक-रहित&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"धारक को किसी Vpn सेवा के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"वॉलपेपर से आबद्ध करें"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"धारक को किसी वॉलपेपर के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"किसी ध्वनि सहभागिताकर्ता से आबद्ध हों"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"धारक को किसी ध्वनि सहभागिता सेवा के शीर्ष-स्तर के इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"रिमोट डिस्प्ले से आबद्ध करें"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"धारक को किसी रिमोट डिस्प्ले के शीर्ष-स्‍तरीय इंटरफ़ेस से आबद्ध होने देती है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"किसी विजेट सेवा से आबद्ध करें"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स  को सूचनाओं को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स  के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"सूचना श्रवणकर्ता सेवा से जुड़ें"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को सूचना श्रवणकर्ता सेवा के शीर्ष स्तरीय इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होनी चाहिए."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"किसी स्थिति प्रदाता सेवा से आबद्ध हों"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"धारक को किसी स्थिति प्रदाता सेवा के शीर्ष-स्तर के इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"वाहक के द्वारा उपलब्ध कराया गया कॉन्फ़िगरेशन ऐप्स  प्रारंभ करें"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"धारक को वाहक के द्वारा उपलब्ध कराया गया कॉन्फ़िगरेशन ऐप्स  प्रारंभ करने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"नेटवर्क स्थितियों के अवलोकनों को सुनें"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"वॉलपेपर"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"वॉलपेपर बदलें"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"सूचना श्रवणकर्ता"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"स्थिति प्रदाता"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN को <xliff:g id="APP">%s</xliff:g> द्वारा सक्रिय किया गया है"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क प्रबंधित करने के लिए स्‍पर्श करें."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 6e44150..a195512 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez naslova&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Nositelju omogućuje vezanje uz sučelje najviše razine VPN usluge. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezano s pozadinskom slikom"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Nositelju omogućuje povezivanje sa sučeljem pozadinske slike najviše razine. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"povezivanje s uslugom glasovne interakcije"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Vlasniku omogućuje povezivanje sa sučeljem najviše razine usluge glasovne interakcije. Nije potrebno za normalne aplikacije."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vezanje uz udaljeni zaslon"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Nositelju omogućuje vezanje uza sučelje najviše razine udaljenog zaslona. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vezanje na uslugu widgeta"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Omogućuje aplikaciji dohvaćanje, pregledavanje i brisanje obavijesti, uključujući obavijesti drugih aplikacija."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vezanje uz uslugu slušatelja obavijesti"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge slušatelja obavijesti. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"povezivanje s uslugom davatelja uvjeta"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Vlasniku omogućuje povezivanje sa sučeljem najviše razine usluge davatelja uvjeta. Nije potrebno za normalne aplikacije."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"pozovi operaterovu aplikaciju za konfiguraciju"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Dopušta nositelju pozivanje operaterove aplikacije za konfiguraciju. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"praćenje motrenja mrežnih uvjeta"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pozadinska slika"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Promjena pozadinske slike"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Slušatelj obavijesti"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Davatalj uvjeta"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> aktivirala je VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite za upravljanje mrežom."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 9697bae..6e82bb8 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Névtelen&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lehetővé teszi a használó számára, hogy csatlakozzon egy VPN-szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"összekapcsolás háttérképpel"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lehetővé teszi, hogy a tulajdonos kötelezővé tegye egy háttérkép legfelső szintű felületét. A normál alkalmazásoknak erre soha nincs szüksége."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"csatlakozás egy hangvezérlőhöz"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Lehetővé teszi a használó számára, hogy csatlakozzon egy hangvezérlő szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"csatlakozás egy távoli kijelzőhöz"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lehetővé teszi a használó számára, hogy csatlakozzon egy távoli kijelző legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"csatlakozás modulszolgáltatáshoz"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Lehetővé teszi, hogy az alkalmazás értesítéseket kérdezzen le, vizsgáljon és tisztítson meg, beleértve az egyéb alkalmazások által közzétett értesítéseket is."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"csatlakozzon értesítésfigyelő szolgáltatáshoz"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lehetővé teszi a használó számára, hogy csatlakozzon egy értesítésfigyelő szolgáltatás legfelső szintű felületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"csatlakozás egy feltételbiztosító szolgáltatáshoz"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Lehetővé teszi a használó számára, hogy csatlakozzon egy feltételbiztosító szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"a szolgáltatói konfigurációs alkalmazás hívása"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lehetővé teszi a használó számára a szolgáltató által biztosított konfigurációs alkalmazás hívását. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"hálózati körülményekkel kapcsolatos észrevételek figyelemmel kísérése"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Háttérkép"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Háttérkép megváltoztatása"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Értesítésfigyelő"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Feltételbiztosító"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiválva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A(z) <xliff:g id="APP">%s</xliff:g> aktiválta a VPN-t"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Érintse meg a hálózat kezeléséhez."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 682e191..12e5fdb 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"Տբ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Պբ"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Անանուն&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 105da53..2fb00bb 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Tanpa judul&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan Vpn. Tidak pernah diperlukan oleh apl normal."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"mengikat ke wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu wallpaper. Tidak pernah diperlukan oleh apl normal."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"mengikat ke pemicu interaksi suara"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Memungkinkan pemegang mengikat antarmuka tingkat tinggi dari layanan interaksi suara. Tidak pernah diperlukan oleh aplikasi normal."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"mengikat ke layar jarak jauh"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Mengizinkan pemegang mengikat ke antarmuka tingkat atas dari layar jarak jauh. Tidak pernah diperlukan untuk aplikasi normal."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"mengikat ke layanan widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Mengizinkan aplikasi mengambil, memeriksa, dan menghapus pemberitahuan, termasuk pemberitahuan yang diposkan oleh aplikasi lain."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"mengikat layanan pendengar pemberitahuan"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Memungkinkan pemegang mengikat antarmuka tingkat teratas dari suatu layanan pendengar pemberitahuan. Tidak pernah diperlukan oleh aplikasi normal."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"mengikat ke layanan penyedia ketentuan"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Memungkinkan pemegang mengikat antarmuka tingkat tinggi dari layanan penyedia ketentuan. Tidak pernah diperlukan oleh aplikasi normal."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"memanggil aplikasi konfigurasi yang disediakan operator"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Memungkinkan pemegang meminta aplikasi konfigurasi yang disediakan operator. Tidak pernah diperlukan aplikasi normal."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"mendengar untuk observasi kondisi jaringan"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ubah wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pendengar pemberitahuan"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Penyedia ketentuan"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengelola jaringan."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 17530b6..af8ed3f 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Senza nome&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Consente l\'associazione all\'interfaccia principale di un servizio VPN. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"associazione a sfondo"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Consente l\'associazione di uno sfondo all\'interfaccia principale. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"collegamento a un servizio di interazione vocale"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio di interazione vocale. Non dovrebbe essere mai necessaria per le normali app."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"collega a un display remoto"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un display remoto. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associazione a un servizio widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Consente all\'app di recuperare, esaminare e cancellare notifiche, comprese quelle pubblicate da altre app."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincolo a un servizio listener di notifica"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Consente al titolare di vincolarsi all\'interfaccia di primo livello di un servizio listener di notifica. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"collegamento a un servizio provider di condizioni"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio provider di condizioni. Non dovrebbe essere mai necessaria per le normali app."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"richiamo dell\'app di configurazione operatore-provider"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Consente al titolare di richiamare l\'app di configurazione dell\'operatore-provider. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ascolto delle osservazioni sulle condizioni di rete"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Sfondo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambia sfondo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Listener di notifica"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provider condizioni"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN attiva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN attivata da <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tocca per gestire la rete."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a633d1f..0157f74 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"‏&gt;ללא כותרת&lt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"‏מאפשר למשתמש לבצע איגוד לממשק ברמה עליונה של שירות VPN. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"קשור לטפט"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"מאפשר למשתמש לבצע איגוד לממשק הרמה העליונה של טפט. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"איגוד לשירות אינטראקציה קולית"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"מאפשרת לבעלים לאגד לממשק ברמה העליונה של שירות אינטראקציה קולית. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"איגוד לצג מרוחק"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"הרשאה זו מאפשרת למשתמש לבצע איגוד לממשק הרמה העליונה של צג רחוק. לעולם אינה אמורה להיות נחוצה לאפליקציות רגילות."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"‏הכפפה לשירות Widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"מאפשר לאפליקציה לאחזר, לבדוק ולמחוק התראות, כולל כאלה שפורסמו על ידי אפליקציות אחרות."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"איגוד לשירות של מאזין להתראות"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"הרשאה זו מאפשרת למשתמש לבצע איגוד לממשק הרמה העליונה של שירות מאזין להתראות. הרשאה זו אף פעם אינה נחוצה לאפליקציות רגילים."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"איגוד לשירות ספק תנאי"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"מאפשרת לבעלים לאגד לממשק ברמה העליונה של שירות ספק תנאי. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"הפעלה של אפליקציית תצורה שסופקה על ידי ספק"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ההרשאה הזו מאפשרת לבעלים להפעיל את אפליקציית התצורה שסופקה על ידי ספק. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"קליטת מעקב אחר תנאי רשת"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"טפט"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"שנה טפט"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"מאזין להתראות"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ספק תנאי"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN מופעל"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"גע כדי לנהל את הרשת."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 8905af6..a9c5cfb 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;新規&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"VPNサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"壁紙にバインド"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"壁紙のトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"音声対話サービスへのバインド"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"音声対話サービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"リモートディスプレイへのバインド"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"リモートディスプレイのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ウィジェットサービスにバインド"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"通知(他のアプリから投稿されたものも含む)を取得、調査、クリアすることをアプリに許可します。"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"通知リスナーサービスにバインド"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"通知リスナーサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"コンディションプロバイダサービスへのバインド"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"コンディションプロバイダサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"携帯通信会社が提供する設定アプリの呼び出し"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"携帯通信会社が提供する設定アプリを呼び出すことを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ネットワーク状況監視のためのリッスン"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁紙"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"壁紙を変更"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知リスナー"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"コンディションプロバイダ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPNが有効になりました"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPNが<xliff:g id="APP">%s</xliff:g>により有効化されました"</string>
     <string name="vpn_text" msgid="3011306607126450322">"タップしてネットワークを管理します。"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index a500b8e..e5ec81b 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"ტბაიტი"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"უსათაურო"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 43199fa..e9a021c 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"តេរ៉ាបៃ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;គ្មាន​ចំណង​ជើង&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម Vpn ។​ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ចង​ទៅ​ផ្ទាំង​រូបភាព"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"ឲ្យ​ម្ចាស់​ចង​ចំណុចប្រទាក់​កម្រិត​កំពូល​នៃ​ផ្ទាំង​រូបភាព។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"ភ្ជាប់​ទៅ​​អ្នក​សហការ​សំឡេង"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​​របស់​សេវាកម្ម​អន្តរកម្ម​សំឡេង។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ភ្ជាប់​ទៅ​ការ​បង្ហាញ​ពី​ចម្ងាយ"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​ការ​បង្ហាញ​ពី​ចម្ងាយ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចង​សេវា​កម្ម​ធាតុ​ក្រាហ្វិក"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"ឲ្យ​កម្មវិធី​ទៅ​យក ពិនិត្យ និង​សម្អាត​ការ​ជូន​ដំណឹង រួមមាន​​ប្រកាស​ដោយ​កម្មវិធី​ផ្សេងៗ។"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ចង​ទៅ​សេវាកម្ម​ស្ដាប់​ការ​ជូន​ដំណឹង"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​កម្មវិធី​ស្ដាប់​ការ​ជូន​ដំណឹង។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​​ទេ។"</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ភ្ជាប់​ទៅ​សេវាកម្ម​ក្រុមហ៊ុន​ផ្ដល់​លក្ខខណ្ឌ"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​​របស់​សេវាកម្ម​ក្រុមហ៊ុន​ផ្ដល់​លក្ខខណ្ឌ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ដកហូត​កម្មវិធី​កំណត់​រចនាសម្ព័ន្ធ​ដែល​បាន​ផ្ដល់​ដោយ​ក្រុមហ៊ុន​បញ្ជូន"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ដក​ហូត​កម្មវិធី​កំណត់​រចនាសម្ព័ន្ធ​ដែល​បាន​ផ្ដល់​ដោយ​ក្រុមហ៊ុន​បញ្ជូន។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"សង្កេត​មើល​លើ​លក្ខខណ្ឌ​បណ្ដាញ"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ផ្ទាំង​រូបភាព"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ប្ដូរ​ផ្ទាំង​រូបភាព"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"កម្មវិធី​ស្ដាប់​ការ​ជូន​ដំណឹង"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ក្រុមហ៊ុន​ផ្ដល់​លក្ខខណ្ឌ"</string>
     <string name="vpn_title" msgid="19615213552042827">"បាន​ធ្វើ​ឲ្យ VPN សកម្ម"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"បាន​ធ្វើ​ឲ្យ VPN សកម្ម​ដោយ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ប៉ះ ដើម្បី​គ្រប់គ្រង​បណ្ដាញ។"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index c01ddd8..7c6feba 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;제목 없음&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"권한을 가진 프로그램이 VPN 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"배경화면 연결"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"권한을 가진 프로그램이 배경화면에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"음성 상호작용 서비스 사용"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"권한을 가진 프로그램이 음성 상호작용 서비스의 최상위 인터페이스를 사용하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"원격 디스플레이에 연결"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"권한을 가진 프로그램이 원격 디스플레이에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"위젯 서비스와 연결"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"앱이 다른 앱에서 게시한 알림을 비롯하여 알림을 검색하고 살펴보며 삭제할 수 있도록 허용합니다."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"알림 수신기 서비스 사용"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"권한을 가진 프로그램이 알림 수신기 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"조건 제공자 서비스 사용"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"권한을 가진 프로그램이 조건 제공자 서비스의 최상위 인터페이스를 사용하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"이동통신사에서 제공한 구성 앱 호출"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"권한을 가진 프로그램이 이동통신사에서 제공한 구성 앱을 호출하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"네트워크 상태에 대한 관측 보고 수신"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"배경화면"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"배경화면 변경"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"알림 수신기"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"조건 제공자"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN이 활성화됨"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN이 <xliff:g id="APP">%s</xliff:g>에 의해 활성화됨"</string>
     <string name="vpn_text" msgid="3011306607126450322">"네트워크를 관리하려면 터치하세요."</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 548d2c0..b31fbff 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;ບໍ່ມີຊື່&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 0b25703..62b6c7a 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Be pavadinimo&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Leidžiama savininkui susisaistyti su aukščiausio lygio VPN paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"susaistyti su darbalaukio fonu"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Leidžiama savininką susaistyti su aukščiausio lygio darbalaukio fono sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"susaistyti su sąveikos balsu priemone"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Turėtojui leidžiama susaistyti programą su sąveikos balsu paslaugos aukščiausio lygio sąsaja. Įprastoms programoms to niekada neturėtų prireikti."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"susisaistyti su nuotoliniu ekranu"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Leidžiama savininkui susisaistyti su aukščiausiojo lygio nuotolinio ekrano sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"susaistyti su valdiklio paslauga"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Programai leidžiama gauti, patikrinti ir išvalyti pranešimus, įskaitant pranešimus, kuriuos paskelbė kitos programos."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"susisaistyti su pranešimų skaitymo priemonės paslauga"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Leidžiama turėtojui susisaistyti su pranešimų skaitymo priemonės paslaugos aukščiausio lygio sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"susaistyti su sąlygos teikėjo paslauga"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Turėtojui leidžiama susaistyti programą su sąlygos teikėjo paslaugos aukščiausio lygio sąsaja. Įprastoms programoms to niekada neturėtų prireikti."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"iškviesti operatoriaus pateiktą konfigūravimo programą"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Turėtojui leidžiama iškviesti operatoriaus pateiktą konfigūravimo programą. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"vykdyti tinklo sąlygų stebėjimą"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Darbalaukio fonas"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Keisti darbalaukio foną"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pranešimų skaitymo priemonė"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Sąlygos teikėjas"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN suaktyvintas"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN suaktyvino „<xliff:g id="APP">%s</xliff:g>“"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Palieskite, kad valdytumėte tinklą."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index f2415d5..b803e61 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez nosaukuma&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Ļauj īpašniekam izveidot saiti ar VPN pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"saistīt ar tapeti"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Ļauj īpašniekam piesaistīt tapetes augstākā līmeņa lietotāja saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"Saistīšana ar balss mijiedarbības elementu"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Ļauj īpašniekam izveidot savienojumu ar balss mijiedarbības pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"Saites izveide ar attālu displeju"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ļauj īpašniekam izveidot saiti ar attāla displeja augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"saistīt ar logrīka pakalpojumu"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ļauj lietotnei izgūt, pārbaudīt un dzēst paziņojumus, tostarp lietotņu publicētos paziņojumus."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"saites izveidošana ar paziņojumu uztvērēja pakalpojumu"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ļauj īpašniekam izveidot saiti ar paziņojumu uztvērēja pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"Saistīšana ar nosacījumu sniedzēja pakalpojumu"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ļauj īpašniekam izveidot savienojumu ar drukas nosacījumu sniedzēja pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Operatora nodrošinātas konfigurācijas lietotnes izsaukšana"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ļauj īpašniekam izsaukt operatora nodrošināto konfigurācijas lietotni. Parastām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"iegūt informāciju par tīkla stāvokļa novērojumiem"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fona tapete"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tapetes maiņa"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Paziņojumu uztvērējs"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Nosacījumu sniedzējs"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ir aktivizēts."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Lietojumprogramma <xliff:g id="APP">%s</xliff:g> aktivizēja VPN."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pieskarieties, lai pārvaldītu tīklu."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 8fd4fba..cc0fa7f 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Гарчиггүй&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Эзэмшигч нь VPN үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ханын зурагтай холбох"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Эзэмшигч нь ханын зурагны дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-уудад шаардлагагүй."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"дуугаар харьцагчтай холбох"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Эзэмшигчид дуугаар харьцах үйлчилгээний дээд-түвшний интерфейстэй холбох боломж олгоно. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"алсын дэлгэцтэй холбогдох"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Эзэмшигчид алсын дэлгэц дэх дээд давхаргын интерфэйстэй холбогдох боломж олгоно. Энгийн апп-д шаардагдахгүй."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"виджет үйлчилгээтэй холбох"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Апп нь бусад апп-уудын илгээсэн мэдэгдлүүдийг дуудах, шалгах, болон цэвэрлэх боломжтой."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"мэдэгдэл сонсогч үйлчилгээтэй холбох"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Эзэмшигч нь мэдэгдэл сонсох үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"нөхцөл нийлүүлэгч үйлчилгээнд холбох"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Эзэмшигчид нөхцөл нийлүүлэгч үйлчилгээний дээд-түвшний интерфейстэй холбох боломж олгоно. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"үүрэн компанийн нийлүүлсэн тохируулгын апп-г өдөөх"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Эзэмшигчид үүрэн компанийн нийлүүлсэн тохируулах апп-г өдөөх боломж олгоно. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Сүлжээний байдлын талаар ажиглалтуудыг хүлээн авах"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ханын зураг"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ханын зураг солих"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Мэдэгдэл сонсогч"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Нөхцөл нийлүүлэгч"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN идэвхтэй болов"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-г <xliff:g id="APP">%s</xliff:g> идэвхтэй болгов"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Сүлжээг удирдах бол хүрнэ үү."</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index d0d4223..53c9b94 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Tidak bertajuk&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 2c90ba3..a67cb28 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Uten navn&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lar innehaveren binde seg til det øverste nivået av grensesnittet for en VPN-tjeneste. Skal aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"binde til bakgrunnsbilde"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lar innehaveren binde det øverste nivået av grensesnittet til en bakgrunn. Skal aldri være nødvendig for vanlige apper."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"binde seg til en tjeneste for talehandlinger"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Gir innehaveren tillatelse til å binde til toppnivået av brukergrensesnittet for en tjeneste for talehandlinger. Dette skal ikke være nødvendig for vanlige apper."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"binde til ekstern skjerm"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lar innehaveren binde seg til det øverste grensesnittnivået for ekstern skjerm. Skal aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"binde til modultjenste"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Lar appen hente, gjennomgå og fjerne varsler, inkludert de som sendes fra andre apper."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"binding til en varsellyttertjeneste"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lar innehaveren binde seg til det øverste grensesnittnivået for en varsellyttertjeneste. Skal aldri være nødvendig for vanlige apper."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"binde seg til en leverandørtjeneste for betingelser"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Gir innehaveren tillatelse til å binde til toppnivået av brukergrensesnittet for en leverandørtjeneste for betingelser. Dette skal ikke være nødvendig for vanlige apper."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"starte konfigurasjonsappen som ble levert av operatøren"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Gir innehaveren tillatelse til å kalle opp den konfigurasjonsappen som ble levert av operatøren. Dette skal ikke være nødvendig for vanlige apper."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"lytte etter observasjoner om nettverksforhold"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrunnsbilde"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Velg bakgrunnsbilde"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Varsellytteren"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Betingelsesleverandør"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktivert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN er aktivert av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Trykk for å administrere nettverket."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 7821648..3b2391f 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Zonder titel&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Staat de houder toe verbinding te maken met de hoofdinterface van een VPN-service. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"verbinden met een achtergrond"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Hiermee wordt de houder toegestaan zich te verbinden met de hoofdinterface van een achtergrond. Nooit vereist voor normale apps."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"binden aan een service voor spraakinteractie"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Hiermee kan de houder binden aan de hoofdinterface van een service voor spraakinteractie. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"verbinding maken met een extern display"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een extern display. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"verbinden met een widgetservice"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Hiermee kan de app meldingen ophalen, onderzoeken en wissen, waaronder meldingen die zijn verzonden door andere apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"koppelen aan een listener-service voor meldingen"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Hiermee kan de houder koppelen aan de hoofdinterface van een listener-service voor meldingen. Nooit vereist voor normale apps."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"binden aan de service van een provider van voorwaarden"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Hiermee kan de houder binden aan de hoofdinterface van de service van een provider van voorwaarden. Nooit vereist voor normale apps."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"de door de provider geleverde configuratie-app aanroepen"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Hiermee kan de houder de door de provider geleverde configuratie-app aanroepen. Nooit vereist voor normale apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"controleren op waarnemingen met betrekking tot netwerkomstandigheden"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Achtergrond"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Achtergrond wijzigen"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Listener voor meldingen"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provider van voorwaarden"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN is geactiveerd"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wordt geactiveerd door <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak aan om het netwerk te beheren."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 3cbd980..b80c1fd 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez nazwy&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Pozwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi VPN. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"powiązanie z tapetą"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Pozwala na tworzenie powiązania z interfejsem najwyższego poziomu tapety. Nieprzeznaczone dla zwykłych aplikacji."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"powiąż z interaktorem głosowym"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi interakcji głosowej. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"powiązanie z wyświetlaczem zdalnym"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu wyświetlacza zdalnego. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"powiązanie z usługą widżetów"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umożliwia aplikacji pobieranie, sprawdzanie i usuwanie powiadomień, także tych, które pochodzą z innych aplikacji."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"utwórz połączenie z usługą odbiornika powiadomień"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi odbiornika powiadomień. Nie powinno być nigdy potrzebne dla zwykłych aplikacji."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"powiąż z usługą dostawcy warunków"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi dostawcy warunków. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"wywoływanie aplikacji konfiguracyjnej udostępnionej przez operatora"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Zezwala na wywoływanie aplikacji konfiguracyjnej udostępnionej przez operatora. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"śledź stan sieci"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmień tapetę"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Odbiornik powiadomień"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Dostawca warunków"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktywny"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Obsługa sieci VPN została włączona przez aplikację <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotknij, aby zarządzać siecią."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 1ad8fad..668f9ef 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sem nome&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite que o titular se vincule à interface de nível superior de um serviço de VPN. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a uma imagem de fundo"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite ao titular vincular-se à interface de nível superior de uma imagem de fundo. Nunca deverá ser necessário para aplicações normais."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"vincular a um interlocutor de voz"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite que o titular vincule a interface de nível superior de um serviço de interação de voz. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"associar a um ecrã remoto"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite ao detentor associar a interface de nível superior a um ecrã remoto. Nunca deve ser necessário para aplicações normais."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a um serviço de widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que a aplicação obtenha, examine e limpe notificações, incluindo as que foram publicadas por outras aplicações."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincular a um serviço de escuta de notificações"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite que o titular vincule a interface de nível superior de um serviço de escuta de notificações. Nunca deverá ser necessário para aplicações normais."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"vincular a um serviço de fornecedor de condição"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite que o titular vincule a interface de nível superior de um serviço de fornecedor de condição. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invocar a aplicação de configuração fornecida pela operadora"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite que o titular invoque a aplicação de configuração fornecida pela operadora. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ouvir observações sobre as condições da rede"</string>
@@ -1131,7 +1149,7 @@
     <string name="Midnight" msgid="5630806906897892201">"Meia-noite"</string>
     <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
-    <string name="selectAll" msgid="6876518925844129331">"Seleccionar tudo"</string>
+    <string name="selectAll" msgid="6876518925844129331">"Selecionar tudo"</string>
     <string name="cut" msgid="3092569408438626261">"Cortar"</string>
     <string name="copy" msgid="2681946229533511987">"Copiar"</string>
     <string name="paste" msgid="5629880836805036433">"Colar"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagem de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar imagem de fundo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviço de escuta de notificações"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fornecedor de condição"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN foi ativada pelo <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerir a rede."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 77e54a4..db493e0 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sem título&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index a4d58411..3103b1f 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -28,6 +28,28 @@
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <!-- no translation found for fileSizeSuffix (9164292791500531949) -->
     <skip />
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <!-- no translation found for untitled (4638956954852782576) -->
     <skip />
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 8a69824..3ee0b8a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TO"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PO"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Fără titlu&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 70e7044..8c7a566 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Без названия&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Приложение сможет подключаться к базовому интерфейсу службы VPN. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"Привязка к фоновому рисунку"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Приложение сможет подключаться к базовому интерфейсу службы обоев. Это разрешение не используется обычными приложениями."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"Подключение к службам голосового взаимодействия"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Приложение сможет подключаться к базовому интерфейсу служб голосового взаимодействия. Это разрешение обычно используется только специальными приложениями."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"Подключение к удаленному дисплею"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Приложение сможет подключаться к базовому интерфейсу удаленного дисплея. Это разрешение обычно используется только специальными приложениями."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"Подключение к службе виджетов"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Приложение сможет получать, проверять и удалять уведомления, включая те, что опубликованы другими приложениями."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"Подключение к службе просмотра уведомлений"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Приложение сможет подключаться к базовому интерфейсу службы просмотра уведомлений. Это разрешение не используется обычными приложениями."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"Подключение к серверам поставщиков условий"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Приложение сможет подключаться к базовому интерфейсу поставщиков условий. Это разрешение обычно используется только специальными приложениями."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Запуск приложения настроек, предоставленного оператором"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Владелец сможет запускать приложение настроек, предоставленное оператором. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Использование данных о состоянии сети"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновый рисунок"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Сменить обои"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Служба просмотра уведомлений"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Поставщик условий"</string>
     <string name="vpn_title" msgid="19615213552042827">"Сеть VPN активна"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Сеть VPN активирована приложением <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Нажмите, чтобы открыть настройки."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 055d23b..c96c661 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez mena&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 2a04337..ef5d872 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Brez naslova&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lastniku omogoča povezovanje z vmesnikom storitve navideznega zasebnega omrežja najvišje ravni. Ne uporabljajte za navadne programe."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezovanje z ozadjem"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Imetniku omogoča povezavo z vmesnikom ozadja najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"povezovanje z glasovnim interaktorjem"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Imetniku omogoča povezovanje z vmesnikom storitve glasovne interakcije najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"povezava z oddaljenim prikazom"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Imetniku omogoča povezovanje z vmesnikom oddaljenega prikaza najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"poveži s storitvijo pripomočka"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Dovoli aplikaciji, da prenese, razišče in izbriše obvestila, tudi tista, ki so jih objavile druge aplikacije."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"poveži se s storitvijo poslušalca obvestil"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lastniku omogoča povezovanje z vmesnikom storitve poslušalca obvestil najvišje ravni. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"povezovanje s storitvijo ponudnika pogojev"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Imetniku omogoča povezovanje z vmesnikom storitve ponudnika pogojev najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"sprožitev operaterjeve aplikacije za konfiguracijo"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lastniku omogoča sproženje operaterjeve aplikacije za konfiguracijo. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"spremljanje razmer v omrežju"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ozadje"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Spreminjanje ozadja"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Poslušalec obvestil"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ponudnik pogojev"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN je aktiviral program <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotaknite se, če želite upravljati omrežje."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 5d03ffa..b87bd89 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Без наслова&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Дозвољава власнику да се повеже са интерфејсом VPN услуге највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"обавезивање на позадину"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Дозвољава власнику да се повеже са интерфејсом позадине највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"повежи са гласовним интерактором"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Дозвољава власнику да се повеже са интерфејсом највишег нивоа услуге гласовне интеракције. Не би требало никада да буде потребно за уобичајене апликације."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"повезивање са удаљеним екраном"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Дозвољава власнику да се повеже са интерфејсом удаљеног екрана највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обавезивање на услугу виџета"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозвољава апликацији да преузима, испитује и брише обавештења, укључујући она која постављају друге апликације."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"повезивање са услугом монитора обавештења"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Дозвољава власнику да се повеже са интерфејсом услуге монитора обавештења највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"повежи са услугом добављача услова"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Дозвољава власнику да се повеже са интерфејсом највишег нивоа услуге добављача услова. Не би требало никада да буде потребно за уобичајене апликације."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"позивање апликације са конфигурацијом коју одређује оператер"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Дозвољава власнику да позива апликацију са конфигурацијом коју одређује оператер. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"праћење података о условима на мрежи"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Позадина"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промена позадине"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Монитор обавештења"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Добављач услова"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN је активиран"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Апликација <xliff:g id="APP">%s</xliff:g> је активирала VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Додирните да бисте управљали мрежом."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 3599074..9b4dae3 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Okänd&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en VPN-tjänst. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"binda till en bakgrund"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Innehavaren kan binda till den översta nivåns gränssnitt för en bakgrund. Ska inte behövas för vanliga appar."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"bind till en röstkomponent"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en rösttjänst. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind till en fjärrskärm"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en fjärrskärm. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind till en widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillåter att appen hämtar, granskar och raderar meddelanden, även sådana som skickats av andra appar."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"binda till en meddelandelyssnare"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en meddelandelyssnare. Ska inte behövas för vanliga appar."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bind till en leverantörstjänst"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en leverantörstjänst. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"anropa konfigurationsappen från operatören"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Innehavaren tillåts att anropa konfigurationsappen från operatören. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"lyssna efter information om nätverksförhållanden"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ändra bakgrund"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Meddelandelyssnare"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Leverantör"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN är aktiverat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveras av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryck om du vill hantera nätverket."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 0c21017..558cae2 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Haina jina&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Inaruhusu kishikiliaji kushurutisha kusano ya kiwango cha juu cha huduma ya Vpn. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"funga kwa mandhari"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Inaruhusu kishikiliaji kushurutisha kwa kusano ya kiwango cha juu cha mandhari. Haipaswi kamwe kuhitajika kwa programu za kawaida."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"shurutisha kwa muingiliano wa sauti"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Humruhusu mmiliki kushurutisha kwa kiolesura cha hali ya juu cha huduma ya muingiliano wa sauti. Kamwe isihitajike kwa programu za kawaida."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"fungisha kwenye mwonekano wa mbali"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Huruhusu mtumiaji kujifungia kiolesura cha kiwango cha juu cha mwonekano wa mbali. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"funga kwenye huduma ya widget"</string>
@@ -418,15 +438,15 @@
     <string name="permdesc_deletePackages" msgid="7411480275167205081">"Inaruhusu programu kufuta furushi za Android. Programu hasidi zinaweza kutumia hii kufuta programu muhimu."</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"Futa data za programu zingine"</string>
     <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"Inaruhusu programu kufuta data ya mtumiaji."</string>
-    <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"Futa kache za programu zingine"</string>
-    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"Inaruhusu programu kufuta faili za kache."</string>
+    <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"Kufuta akiba za programu zingine"</string>
+    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"Huruhusu programu kufuta faili za akiba."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"Pima nafasi ya hifadhi ya programu"</string>
-    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Inaruhusu Programu kupata tena msimbo, data na ukubwa wa kache yake."</string>
+    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Huruhusu Programu kupata tena msimbo, data na ukubwa wa akiba yake"</string>
     <string name="permlab_installPackages" msgid="2199128482820306924">"sakinisha programu moja kwa moja"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Inaruhusu programu kusakanisha au kusasisha furushi mpya za Android. Programu hasidi zinaweza kutumia hii kuongeza programu mpya ambazo zina ruhusa zenye nguvu."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"kufuta data yote kwenye akiba ya programu"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Inaruhusu programu kutoa nafasi ya hifadhi ya kompyuta ndogo kwa kufuta faili katika saraka za kache za programu nyingine. Huenda hii ikasababisha programu nyingine kuanza polepole zaidi kwa sababu zinahitaji kuepua data zazo."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Inaruhusu programu kutoa nafasi ya hifadhi ya simu kwa kufuta faili katika saraka za kache za programu nyingine. Huenda hii ikasababisha programu nyingine kuanza polepole zaidi kwa sababu zinahitaji kuepua data zazo."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Huruhusu programu kuongeza nafasi katika hifadhi ya kompyuta kibao kwa kufuta faili katika saraka za akiba za programu zingine. Huenda hii ikafanya baadhi ya programu zianze kufanya kazi polepole kwa sababu zinahitaji kupakua tena data iliyokuwemo."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Huruhusu programu kuongeza nafasi ya hifadhi ya simu kwa kufuta faili katika saraka za akiba za programu zingine. Huenda hii ikafanya baadhi ya programu zianze kufanya kazi polepole kwa sababu zinahitaji kupakua tena data iliyokuwemo."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"songesha rasilimali ya programu"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Huruhusu programu kuhamisha nyenzo za programu kutoka midia ya ndani hadi ya nje na kinyume chake."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"soma kumbukumbu ya data muhimu"</string>
@@ -577,7 +597,7 @@
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"badiliisha hali ya simu"</string>
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Inaruhusu programu kudhibiti vipengee vya kifaa. Programu iliyo na ruhusa hii inaweza badilisha mtandao, kuzima na kuwasha redio ya simu bila hata kukujulisha."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"kusoma hali na kitambulisho cha simu"</string>
-    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Inaruhusu programu kufikia vipengele vya simu vya kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama simu ni amilifu, na nambari ya mbali iliyounganishwa kwa simu."</string>
+    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Huruhusu programu kufikia vipengele vya simu vilivyo kwenye kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama kuna simu inayopigwa, na nambari ya mbali iliyounganishwa kwenye simu."</string>
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"Soma hali sahihi ya simu"</string>
     <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Huruhusu programu kufikia hali sahihi ya simu. Ruhusa hii huwezesha programu kufahamu hali sahihi ya simu, iwapo simu inatumika au iko katika hali ya chini kwa chini, simu inaposhindikana, hali sahihi ya muunganisho wa data na muunganisho wa data unaposhindikana."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zuia kompyuta ndogo dhidi ya kulala"</string>
@@ -685,12 +705,12 @@
     <string name="permdesc_manageDocs" product="default" msgid="8704323176914121484">"Huruhusu programu kudhibiti hifadhi ya hati."</string>
     <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"Fikia hifadhi ya nje ya watumiaji wote"</string>
     <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Inaruhusu programu kufikia hifadhi ya nje kwa watumiaji wote."</string>
-    <string name="permlab_cache_filesystem" msgid="5656487264819669824">"fikia faili za mfumo za kache"</string>
-    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Inaruhusu programu kusoma na kuandika mfumo wa faili wa kache."</string>
+    <string name="permlab_cache_filesystem" msgid="5656487264819669824">"fikia faili za mfumo za akiba"</string>
+    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Huruhusu programu kusoma na kuandika mfumo wa faili wa akiba."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"piga/pokea simu za mtandao"</string>
     <string name="permdesc_use_sip" msgid="4717632000062674294">"Inaruhusu programu kutumia huduma ya SIP kupiga/kupokea simu za mtandao."</string>
     <string name="permlab_bind_call_service" msgid="6724009726671246551">"tumikisha skrini ya simu inayoendelea"</string>
-    <string name="permdesc_bind_call_service" msgid="8732547662442572435">"Inaruhusu programu kudhibiti wakati na jinsi mtumiaji anaona skrini ya simu inayoendelea."</string>
+    <string name="permdesc_bind_call_service" msgid="8732547662442572435">"Huruhusu programu kudhibiti wakati na jinsi mtumiaji anaona skrini anapopigiwa simu."</string>
     <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"soma matumizi ya historia ya mtandao"</string>
     <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Inaruhusu programu kusoma historia ya matumizi ya mtandao kwa mitandao maalum na programu."</string>
     <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"dhibiti sera ya mtandao"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Huruhusu programu kurejesha, kuchunguza, na kuondoa arifa, ikiwa ni pamoja na zile zilizochapishwa na programu nyingine."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"unganisha kwenye huduma ya kisikilizi cha arifa"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Inaruhusu kishikilizi kuunganishwa kwenye kusano cha kiwango cha juu cha huduma ya kisikilizi cha arifa. Haipaswi kuhitajika tena kwa programu za kawaida."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"shurutisha kwa huduma ya mtoa masharti"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Humruhusu mmiliki kushurutisha kwa kiolesura cha kiwango cha juu cha huduma ya mtoa masharti. Kamwe isihitajike kwa pogramu za kawaida."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"omba programu ya usakinishaji inayotolewa na mtoa huduma."</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Inaruhusu kishikiliaji kuomba programu ya usakinishaji inayotolewa na mto huduma. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"sikiliza matukio katika hali za mtandao"</string>
@@ -717,9 +735,9 @@
     <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Huruhusu programu kwa utoaji na matumizi ya vyeti vya DRM. Havifahi kuhitajika kwa ajili ya programu za kawaida."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Kuweka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kudhibiti urefu na herufi zinazoruhusiwa katika manenosiri ya kufungua skrini."</string>
-    <string name="policylab_watchLogin" msgid="914130646942199503">"Kuhesabu idadi ya mara ambazo skrini inajaribu kufunguliwa"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Fuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na ufunge kompyuta kibao au ufute data yote iliyomo kama manenosiri mengi yenye makosa yataingizwa."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Fuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na ufunge simu au ufute data yote iliyomo kama manenosiri mengi sana yasiyo sahihi yataingizwa."</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Kuhesabu mara ambazo skrini inajaribu kufunguliwa"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Kufuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na kufunga kompyuta kibao au kufuta data yote iliyomo kama manenosiri mengi yasiyo sahihi yataingizwa."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Kufuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na kufunga simu au kufuta data yote iliyomo kama manenosiri mengi sana yasiyo sahihi yataingizwa."</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"Kubadilisha nenosiri la kufungua skrini"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"Kubadilisha nenosiri la kufungua skrini."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Kufunga skrini"</string>
@@ -1296,14 +1314,14 @@
     <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Imeunganishwa kama kamera"</string>
     <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Imeunganishwa kama kisakinishi"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"Imeunganishwa kwa kifuasi cha USB"</string>
-    <string name="usb_notification_message" msgid="2290859399983720271">"Gusa kwa chaguo nyingine za USB."</string>
+    <string name="usb_notification_message" msgid="2290859399983720271">"Gusa ili uone chaguo zingine za USB."</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="9020092196061007262">"Fomati hifadhi ya USB?"</string>
     <string name="extmedia_format_title" product="default" msgid="3648415921526526069">"Umbiza kadi ya SD."</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"Faili zote zilizohifadhiwa katika hifadhi yako ya USB zitafutwa. Hatua hii haiwezi kubadilishwa!"</string>
     <string name="extmedia_format_message" product="default" msgid="14131895027543830">"Data yote kwenye kadi yako itapotea."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Fomati"</string>
-    <string name="adb_active_notification_title" msgid="6729044778949189918">"Utatuaji USB umeunganishwa"</string>
-    <string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili kulemaza utatuaji wa USB."</string>
+    <string name="adb_active_notification_title" msgid="6729044778949189918">"Utatuaji wa USB umeunganishwa"</string>
+    <string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili uzime utatuaji wa USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Chagua njia ya ingizo"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Weka mbinu za ingizo"</string>
     <string name="use_physical_keyboard" msgid="6203112478095117625">"Kibodi halisi"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Mandhari"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha mandhari"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Kisikilizi cha arifa"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Mtoa hali"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN imewezeshwa"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN imeamilishwa na <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Gusa ili kudhibiti mtandao."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ded9706..826fa64 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;ไม่มีชื่อ&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"อนุญาตให้เจ้าของเชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของบริการ VPN ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"เชื่อมโยงกับวอลเปเปอร์"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของวอลเปเปอร์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"เชื่อมโยงกับโปรแกรมโต้ตอบด้วยเสียง"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"อนุญาตให้ผู้ใช้อุปกรณ์เชื่อมโยงกับอินเทอร์เฟซระดับบนสุดของบริการโต้ตอบด้วยเสียง ไม่จำเป็นสำหรับแอปทั่วไป"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ผูกกับจอแสดงผลระยะไกล"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"อนุญาตให้ผู้ใช้ผูกกับอินเทอร์เฟซระดับสูงสุดของจอแสดงผลระยะไกล ซึ่งแอปพลิเคชันทั่วไปไม่จำเป็นต้องใช้"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"เชื่อมโยงกับบริการวิดเจ็ต"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"ทำให้แอปสามารถเรียกดู ตรวจสอบ และล้างการแจ้งเตือนได้ ซึ่งรวมถึงการแจ้งเตือนที่โพสต์โดยแอปอื่นๆ ด้วย"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"เชื่อมโยงกับบริการตัวฟังการแจ้งเตือน"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"อนุญาตให้เจ้าของเชื่อมโยงกับอินเตอร์เฟซระดับสูงสุดของบริการตัวฟังการแจ้งเตือน ซึ่งไม่มีความจำเป็นสำหรับแอปธรรมดา"</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"เชื่อมโยงกับบริการของผู้เสนอเงื่อนไข"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"อนุญาตให้ผู้ใช้อุปกรณ์เชื่อมโยงกับอินเทอร์เฟซระดับบนสุดของบริการของผู้เสนอเงื่อนไข ไม่จำเป็นสำหรับแอปทั่วไป"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"เรียกใช้แอปการกำหนดค่าของผู้ให้บริการ"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"อนุญาตให้ผู้ใช้สามารถเรียกใช้แอปการกำหนดค่าของผู้ให้บริการ ซึ่งแอปทั่วไปไม่จำเป็นต้องใช้"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ฟังข้อสังเกตเกี่ยวกับสภาวะของเครือข่าย"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"วอลเปเปอร์"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"เปลี่ยนวอลเปเปอร์"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ตัวฟังการแจ้งเตือน"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ผู้เสนอเงื่อนไข"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN เปิดใช้งานแล้ว"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"เปิดใช้งาน VPN โดย <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"แตะเพื่อจัดการเครือข่าย"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 4d2d0db..6e50517 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Walang pamagat&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng serbisyo ng Vpn. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sumailalim sa wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng isang wallpaper. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"i-bind sa isang voice interactor"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Nagbibigay-daan sa may-hawak na i-bind ang top-level na interface ng isang serbisyo sa pakikipag-ugnayan gamit ang boses. Hindi kailanman dapat kailanganin ng mga normal na app."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"magpasaklaw sa isang remote na display"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Binibigyang-daan ang may-hawak na masaklaw ang pinakamataas na antas ng interface ng isang remote na display. Hindi dapat kailanman kailanganin ng normal na apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"itali sa serbisyo ng widget"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Pinapayagan ang app na kumuha, sumuri, at mag-clear ng mga notification, kabilang ang mga na-post ng iba pang apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"mapailalim sa isang serbisyo ng notification listener"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Nagbibigay-daan sa may-ari na mapailalim sa interface sa tuktok na antas ng isang serbisyo ng notification listener. Hindi dapat kailanganin para sa karaniwang apps kahit kailan."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"i-bind sa isang serbisyo sa pagbibigay ng kundisyon"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Nagbibigay-daan sa naghahawak na i-bind ang top-level na interface ng isang serbisyo sa pagbibigay ng kundisyon. Hindi kailanman dapat kailanganin ng mga normal na app."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"paganahin ang app ng configuration na ibinigay ng carrier"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Nagbibigay-daan sa may-ari na paganahin ang app ng configuration na ibinigay ng carrier. Hindi dapat kailanganin para sa normal na apps kahit kailan."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"makinig sa mga obserbasyon sa mga kundisyon ng network"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Baguhin ang wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Nagbibigay ng kundisyon"</string>
     <string name="vpn_title" msgid="19615213552042827">"Naka-activate ang VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Isinaaktibo ang VPN ng <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pindutin upang pamahalaan ang network."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8c97507..bd2f926 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Adsız&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Cihazın sahibine bir VPN hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bir duvar kağıdına tabi kıl"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Cihazın sahibine, duvar kağıdının en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"bir ses etkileşimi hizmetine bağlanma"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"İzin sahibinin, bir ses etkileşimi hizmetine ait üst düzey arayüze bağlanmasına izin verir. Normal uygulamalar için hiçbir zaman gerekli değildir."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"uzak ekrana bağlan"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"İzin sahibine, bir uzak ekranın en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bir widget hizmetine bağla"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Uygulamanın bildirimler almasına, bildirimleri incelemesine ve temizlemesine izin verir. Buna diğer uygulamalar tarafından yayınlanan bildirimler de dahildir."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bildirim dinleyici hizmetine bağlan"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"İzin sahibine bir bildirim dinleyici hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bir durum sağlayıcı hizmetine bağlanma"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"İzin sahibinin, bir durum sağlayıcı hizmete ait üst düzey arayüze bağlanmasına izin verir. Normal uygulamalar için hiçbir zaman gerekli değildir."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"operatör tarafından sağlanan yapılandırma uygulamasını çalıştır"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"İzin sahibine, operatör tarafından sağlanan yapılandırma uygulamasını çalıştırma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ağ koşullarındaki gözlemleri dinle"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Duvar Kağıdı"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Duvar kağıdını değiştir"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildirim dinleyici"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Durum sağlayıcı"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN etkinleştirildi"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN, <xliff:g id="APP">%s</xliff:g> tarafından etkinleştirildi"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Ağı yönetmek için dokunun."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 104a45c..d01c5776 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"Тб"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Пб"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Без назви&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби VPN. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"прив’язати до фонового малюнка"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Дозволяє власнику прив’язуватися до інтерфейсу верхнього рівня фонового малюнка. Ніколи не застосовується для звичайних програм."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"підключитися до служби голосової взаємодії"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Додаток зможе підключатися до інтерфейсу верхнього рівня служби голосової взаємодії. Звичайні додатки ніколи не використовують цей дозвіл."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"прив’язуватися до віддаленого екрана"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня віддаленого екрана. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"прив\'язувати до служби віджетів"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозволяє програмі отримувати, перевіряти й очищати сповіщення, зокрема опубліковані іншими програмами."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"прив’язуватися до служби читання сповіщень"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Дозволяє власнику прив’язуватися до інтерфейсу верхнього рівня служби читання сповіщень. Ніколи не застосовується для звичайних програм."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"підключитися до служби постачання умов"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Додаток зможе підключатися до інтерфейсу верхнього рівня служби постачання умов. Звичайні додатки ніколи не використовують цей дозвіл."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"викликати надану оператором програму конфігурації"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Дозволяє власнику викликати надану оператором програму конфігурації. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"прослуховувати дані спостережень за станом мережі"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновий мал."</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Змінити фоновий малюнок"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Служба читання сповіщень"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Постачальник умов"</string>
     <string name="vpn_title" msgid="19615213552042827">"Мережу VPN активовано"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Мережу VPN активовано програмою <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Торкніться, щоб керувати мережею."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 24d468c..24b2db5 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Không có tiêu đề&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ Vpn. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"liên kết với hình nền"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của hình nền. Không cần thiết cho các ứng dụng thông thường."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"liên kết với trình tương tác bằng giọng nói"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ tương tác bằng giọng nói. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"liên kết với màn hình từ xa"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của màn hình từ xa. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"liên kết với dịch vụ tiện ích con"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Cho phép ứng dụng truy xuất, kiểm tra và xóa thông báo, bao gồm những thông báo được đăng bởi các ứng dụng khác."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"liên kết với dịch vụ trình xử lý thông báo"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ trình xử lý thông báo. Không cần thiết cho các ứng dụng thông thường."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"liên kết với dịch vụ trình cung cấp điều kiện"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ trình cung cấp điều kiện. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gọi ra ứng dụng cấu hình do nhà cung cấp dịch vụ cung cấp"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Cho phép chủ sở hữu gọi ra ứng dụng cấu hình do nhà cung cấp dịch vụ cung cấp. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"quan sát các điều kiện mạng"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hình nền"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Thay đổi hình nền"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Trình xử lý thông báo"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Trình cung cấp điều kiện"</string>
     <string name="vpn_title" msgid="19615213552042827">"Đã kích hoạt VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN được <xliff:g id="APP">%s</xliff:g> kích hoạt"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Chạm để quản lý mạng."</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index 4c4d0ce..44e258d 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -27,4 +27,14 @@
         <item>settings</item>
     </string-array>
 
-</resources>
\ No newline at end of file
+    <!-- Base "touch slop" value used by ViewConfiguration as a
+         movement threshold where scrolling should begin. -->
+    <dimen name="config_viewConfigurationTouchSlop">4dp</dimen>
+
+    <!-- Minimum velocity to initiate a fling, as measured in dips per second. -->
+    <dimen name="config_viewMinFlingVelocity">500dp</dimen>
+
+    <!-- Maximum velocity to initiate a fling, as measured in dips per second. -->
+    <dimen name="config_viewMaxFlingVelocity">8000dp</dimen>
+
+</resources>
diff --git a/core/res/res/values-watch/themes.xml b/core/res/res/values-watch/themes.xml
new file mode 100644
index 0000000..9447d9cb
--- /dev/null
+++ b/core/res/res/values-watch/themes.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.
+-->
+<resources>
+    <style name="Theme.Dialog.Alert" parent="Theme.Micro.Dialog.Alert" />
+    <style name="Theme.Dialog.AppError" parent="Theme.Micro.Dialog.AppError" />
+    <style name="Theme.Holo.Dialog.Alert" parent="Theme.Micro.Dialog.Alert" />
+    <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Micro.Dialog.Alert" />
+</resources>
diff --git a/core/res/res/values-watch/themes_device_defaults.xml b/core/res/res/values-watch/themes_device_defaults.xml
new file mode 100644
index 0000000..705143c
--- /dev/null
+++ b/core/res/res/values-watch/themes_device_defaults.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+<resources>
+    <style name="Theme.DeviceDefault" parent="Theme.Micro" />
+    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Micro" />
+    <style name="Theme.DeviceDefault.Dialog" parent="Theme.Micro.Dialog" />
+    <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Micro.Dialog.Alert" />
+    <style name="Theme.DeviceDefault.Light" parent="Theme.Micro.Light" />
+    <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Micro.Light" />
+    <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Micro.Light" />
+    <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Micro.Dialog" />
+    <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Micro.Dialog.Alert" />
+
+</resources>
+
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 95ec384..9297e3a 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index d78f298..1c8cfe8 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允許應用程式繫結至 VPN 服務的頂層介面 (不建議一般應用程式使用)。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"繫結至桌布"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允許應用程式繫結至桌布的頂層介面 (不建議一般應用程式使用)。"</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"繫結至語音互動器"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"允許應用程式繫結至語音互動服務的頂層介面,但一般應用程式並不需要使用。"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"繫結至遠端螢幕"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允許應用程式繫結至遠端屏螢的頂層介面 (不建議一般應用程式使用)。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"允許應用程式擷取、檢查及清除通知 (包括由其他應用程式發佈的通知)。"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"繫結至通知接聽器服務"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允許應用程式繫結至通知接聽器服務的頂層介面 (不建議一般應用程式使用)。"</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"繫結至條件供應商服務"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允許應用程式繫結至條件供應商服務的頂層介面,但一般應用程式並不需要使用。"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"調用流動網絡供應商提供的設定應用程式"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允許應用程式調用流動網絡供應商提供的設定應用程式 (不建議一般應用程式使用)。"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"監聽對網絡狀況的觀察"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知接聽器"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"條件供應商"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN 已啟用。"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網絡。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 38a487b..05e0894 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允許應用程式聯繫至 VPN 服務的頂層介面 (一般應用程式不需使用)。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"連結至桌布"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允許應用程式繫結至桌布的頂層介面 (一般應用程式不需使用)。"</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"繫結至語音互動器"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"允許應用程式繫結至語音互動服務的頂層介面 (一般應用程式並不需要)。"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"繫結至遠端螢幕"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允許應用程式繫結至遠端螢幕的頂層介面 (一般應用程式不需使用)。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"允許應用程式擷取、檢查及清除通知 (包括由其他應用程式發佈的通知)。"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"繫結至通知接聽器服務"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允許應用程式繫結至通知接聽器服務的頂層介面 (一般應用程式不需使用)。"</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"繫結至條件提供者服務"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允許應用程式繫結至條件提供者服務的頂層介面 (一般應用程式並不需要)。"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"叫用行動通訊業者提供的設定應用程式"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允許應用程式叫用行動通訊業者提供的設定應用程式 (一般應用程式並不需要)。"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"監聽網路狀況觀察資訊"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知接聽器"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"條件提供者"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN 已啟用"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網路。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index ede3d3c..9c8542e 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Akunasihloko&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -387,10 +409,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Ivumela umnini ukuthi abophele kwissekelo esingaphezulu sesevisi ye-Vpm. Ayidingakeli izinhlelo zokusebenza ezejwayelekile."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"hlanganisa kwiphephadonga"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lwephephadonga. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"hlanganisa kusisebenzisani sezwi"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Ivumela umbambi ukuhlanganisa isixhumi esibonakalayo sesevisi yokusebenzisana yezwi. Akufanele kudingekele izinhlelo zokusebenza ezivamile."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bophezela kusibonisi sesilawuli kude"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ivumela umbambi ukuhlanganisa isixhumi esibonakalayo esisezingeni eliphezulu sesibonisi sesilawuli kude. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bophezela kube isevisi yesinqunjana"</string>
@@ -703,10 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ivumela uhlelo lokusebenza ukuthi lithole, lihlole, liphinde lisuse izaziso, ezifaka lezo ezithunyelwe ezinye izinhlelo zokusebenza."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bophezela kwisevisi yomlaleli wesaziso"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ivumela umbambi ukubophezela kwisixhumi esibonakalayo sezinga eliphezulu lesevisi yomlaleli wesaziso. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"hlanganisa kwisevisi yomhlinzeki wesimo"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ivumela umbambi ukuhlanganisa isixhumi esibonakalayo seleveli ephezulu sesevisi yomhlinzeki wesimo. Akufanele kudingekele izinhlelo zokusebenza ezivamile."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"buyisela uhlelo lokusebenza lokulungiselelwa okunikezwe yinkampani yenethiwekhi"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ivumela umnikazi ukuthi abuyisele uhlelo lokusebenza lokulungiselelwa. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Lalela okubonwayo kuzimo zenethiwekhi"</string>
@@ -1377,8 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Iphephadonga"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Shintsha iphephadonga"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Umlaleli wesaziso"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Umhlinzeki wesimo"</string>
     <string name="vpn_title" msgid="19615213552042827">"I-VPN isiyasebenza"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"i-VPN ivuswe ngu <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Thinta ukuze wengamele inethiwekhi."</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index f01f10e..305ba28 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -348,4 +348,43 @@
         <item>中文 (繁體)</item>
     </string-array>
 
+    <!-- Used by callers to Resources.selectSystemTheme(). Defines the minimum
+         targetSdkVersion required for the theme style at a given index.
+         NOTE: Must be sorted in ascending order. -->
+    <integer-array name="system_theme_sdks">
+        <item>0</item>
+        <item>11</item>
+        <item>14</item>
+        <item>21</item>
+    </integer-array>
+
+    <!-- Used by Resources.selectDefaultTheme(). Defines the default theme style
+         for the targetSdkVersion at a given index (see system_theme_sdks).
+         NOTE: Must match number of entries in system_theme_sdks. -->
+    <array name="system_theme_styles">
+        <item>@style/Theme</item>
+        <item>@style/Theme.Holo</item>
+        <item>@style/Theme.DeviceDefault</item>
+        <item>@style/Theme.DeviceDefault.Light.DarkActionBar</item>
+    </array>
+
+    <!-- Used by ContextImpl for notifications. Defines the default dialog theme
+         style for the targetSdkVersion at a given index (see system_theme_sdks).
+         NOTE: Must match number of entries in system_theme_sdks. -->
+    <array name="system_theme_dialog_styles">
+        <item>@style/Theme</item>
+        <item>@style/Theme.Holo.Dialog</item>
+        <item>@style/Theme.DeviceDefault.Dialog</item>
+        <item>@style/Theme.DeviceDefault.Light.Dialog</item>
+    </array>
+
+    <!-- Used by InputMethodService.onCreate(). Defines the default IME theme
+         style for the targetSdkVersion at a given index (see system_theme_sdks).
+         NOTE: Must match number of entries in system_theme_sdks. -->
+    <array name="system_theme_ime_styles">
+        <item>@style/Theme.InputMethod</item>
+        <item>@style/Theme.Holo.InputMethod</item>
+        <item>@style/Theme.DeviceDefault.InputMethod</item>
+        <item>@style/Theme.DeviceDefault.InputMethod</item>
+    </array>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index efc1b55..7036224 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -966,7 +966,6 @@
         <attr name="colorButtonPressed" format="color" />
         <attr name="colorButtonNormalColored" format="color" />
         <attr name="colorButtonPressedColored" format="color" />
-
     </declare-styleable>
 
     <!-- **************************************************************** -->
@@ -5811,6 +5810,9 @@
         <attr name="imeExtractExitAnimation" format="reference" />
     </declare-styleable>
 
+    <declare-styleable name="VoiceInteractionSession">
+    </declare-styleable>
+
     <declare-styleable name="KeyboardView">
         <!-- Default KeyboardView style. -->
         <attr name="keyboardViewStyle" format="reference" />
@@ -6348,6 +6350,8 @@
         <!-- Specifies padding that should be applied to the left and right sides of
              system-provided items in the bar. -->
         <attr name="itemPadding" format="dimension" />
+        <!-- Set true to hide the action bar on a vertical nested scroll of content. -->
+        <attr name="hideOnContentScroll" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="ActionMode">
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index d0c455b..761170d 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -71,11 +71,7 @@
     <drawable name="editbox_dropdown_dark_frame">@drawable/editbox_dropdown_background_dark</drawable>
     <drawable name="editbox_dropdown_light_frame">@drawable/editbox_dropdown_background</drawable>
 
-    <drawable name="dialog_holo_dark_frame">@drawable/dialog_full_holo_dark</drawable>
-    <drawable name="dialog_holo_light_frame">@drawable/dialog_full_holo_light</drawable>
-
     <drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
-    <drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable>
     <color name="input_method_navigation_guard">#ff000000</color>
 
     <!-- For date picker widget -->
@@ -122,73 +118,7 @@
     <!-- FaceLock -->
     <color name="facelock_spotlight_mask">#CC000000</color>
 
-    <!-- For holo theme -->
-    <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
-    <drawable name="screen_background_holo_dark">#ff000000</drawable>
-    <color name="background_holo_dark">#ff000000</color>
-    <color name="background_holo_light">#fff3f3f3</color>
-    <color name="bright_foreground_holo_dark">@android:color/background_holo_light</color>
-    <color name="bright_foreground_holo_light">@android:color/background_holo_dark</color>
-    <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
-    <color name="bright_foreground_disabled_holo_light">#ffb2b2b2</color>
-    <color name="bright_foreground_inverse_holo_dark">@android:color/bright_foreground_holo_light</color>
-    <color name="bright_foreground_inverse_holo_light">@android:color/bright_foreground_holo_dark</color>
-    <color name="dim_foreground_holo_dark">#bebebe</color>
-    <color name="dim_foreground_disabled_holo_dark">#80bebebe</color>
-    <color name="dim_foreground_inverse_holo_dark">#323232</color>
-    <color name="dim_foreground_inverse_disabled_holo_dark">#80323232</color>
-    <color name="hint_foreground_holo_dark">#808080</color>
-    <color name="dim_foreground_holo_light">#323232</color>
-    <color name="dim_foreground_disabled_holo_light">#80323232</color>
-    <color name="dim_foreground_inverse_holo_light">#bebebe</color>
-    <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
-    <color name="hint_foreground_holo_light">#808080</color>
-    <color name="highlighted_text_holo_dark">#6633b5e5</color>
-    <color name="highlighted_text_holo_light">#6633b5e5</color>
-    <color name="link_text_holo_dark">#5c5cff</color>
-    <color name="link_text_holo_light">#0000ee</color>
-
-    <!-- Group buttons -->
-    <eat-comment />
-    <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
-    <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
-
-    <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
-    <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
-
-    <!-- Highlight colors for the legacy themes -->
-    <eat-comment />
-    <color name="legacy_pressed_highlight">#fffeaa0c</color>
-    <color name="legacy_selected_highlight">#fff17a0a</color>
-    <color name="legacy_long_pressed_highlight">#ffffffff</color>
-
-    <!-- General purpose colors for Holo-themed elements -->
-    <eat-comment />
-
-    <!-- A light Holo shade of blue -->
-    <color name="holo_blue_light">#ff33b5e5</color>
-    <!-- A light Holo shade of gray -->
-    <color name="holo_gray_light">#33999999</color>
-    <!-- A light Holo shade of green -->
-    <color name="holo_green_light">#ff99cc00</color>
-    <!-- A light Holo shade of red -->
-    <color name="holo_red_light">#ffff4444</color>
-    <!-- A dark Holo shade of blue -->
-    <color name="holo_blue_dark">#ff0099cc</color>
-    <!-- A dark Holo shade of green -->
-    <color name="holo_green_dark">#ff669900</color>
-    <!-- A dark Holo shade of red -->
-    <color name="holo_red_dark">#ffcc0000</color>
-    <!-- A Holo shade of purple -->
-    <color name="holo_purple">#ffaa66cc</color>
-    <!-- A light Holo shade of orange -->
-    <color name="holo_orange_light">#ffffbb33</color>
-    <!-- A dark Holo shade of orange -->
-    <color name="holo_orange_dark">#ffff8800</color>
-    <!-- A really bright Holo shade of blue -->
-    <color name="holo_blue_bright">#ff00ddff</color>
-    <!-- A really bright Holo shade of gray -->
-    <color name="holo_gray_bright">#33CCCCCC</color>
+    <color name="micro_text_light">#434343</color>
 
     <drawable name="notification_template_icon_bg">#3333B5E5</drawable>
     <drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
@@ -204,21 +134,5 @@
 
     <color name="accessibility_focus_highlight">#80ffff00</color>
 
-    <!-- New TimePicker colors -->
-    <color name="timepicker_default_background_holo_light">@android:color/white</color>
-    <color name="timepicker_default_background_holo_dark">#ff303030</color>
-
-    <color name="timepicker_default_text_color_holo_light">#8c8c8c</color>
-    <color name="timepicker_default_text_color_holo_dark">@android:color/white</color>
-
-    <color name="timepicker_default_disabled_color_holo_light">#7f000000</color>
-    <color name="timepicker_default_disabled_color_holo_dark">#7f08c8c8</color>
-
-    <color name="timepicker_default_ampm_selected_background_color_holo_light">@android:color/holo_blue_light</color>
-    <color name="timepicker_default_ampm_selected_background_color_holo_dark">@android:color/holo_blue_light</color>
-
-    <color name="timepicker_default_ampm_unselected_background_color_holo_light">@android:color/white</color>
-    <color name="timepicker_default_ampm_unselected_background_color_holo_dark">@android:color/transparent</color>
-
 </resources>
 
diff --git a/core/res/res/values/colors_holo.xml b/core/res/res/values/colors_holo.xml
new file mode 100644
index 0000000..d1f4e38
--- /dev/null
+++ b/core/res/res/values/colors_holo.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Colors specific to Holo themes. -->
+<resources>
+
+    <drawable name="dialog_holo_dark_frame">@drawable/dialog_full_holo_dark</drawable>
+    <drawable name="dialog_holo_light_frame">@drawable/dialog_full_holo_light</drawable>
+    <drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable>
+
+    <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
+    <drawable name="screen_background_holo_dark">#ff000000</drawable>
+
+    <color name="background_holo_dark">#ff000000</color>
+    <color name="background_holo_light">#fff3f3f3</color>
+    <color name="bright_foreground_holo_dark">@color/background_holo_light</color>
+    <color name="bright_foreground_holo_light">@color/background_holo_dark</color>
+    <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
+    <color name="bright_foreground_disabled_holo_light">#ffb2b2b2</color>
+    <color name="bright_foreground_inverse_holo_dark">@color/bright_foreground_holo_light</color>
+    <color name="bright_foreground_inverse_holo_light">@color/bright_foreground_holo_dark</color>
+    <color name="dim_foreground_holo_dark">#bebebe</color>
+    <color name="dim_foreground_disabled_holo_dark">#80bebebe</color>
+    <color name="dim_foreground_inverse_holo_dark">#323232</color>
+    <color name="dim_foreground_inverse_disabled_holo_dark">#80323232</color>
+    <color name="hint_foreground_holo_dark">#808080</color>
+    <color name="dim_foreground_holo_light">#323232</color>
+    <color name="dim_foreground_disabled_holo_light">#80323232</color>
+    <color name="dim_foreground_inverse_holo_light">#bebebe</color>
+    <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
+    <color name="hint_foreground_holo_light">#808080</color>
+    <color name="highlighted_text_holo_dark">#6633b5e5</color>
+    <color name="highlighted_text_holo_light">#6633b5e5</color>
+    <color name="link_text_holo_dark">#5c5cff</color>
+    <color name="link_text_holo_light">#0000ee</color>
+
+    <!-- General purpose colors for Holo-themed elements -->
+    <eat-comment />
+
+    <!-- A light Holo shade of blue -->
+    <color name="holo_blue_light">#ff33b5e5</color>
+    <!-- A light Holo shade of gray -->
+    <color name="holo_gray_light">#33999999</color>
+    <!-- A light Holo shade of green -->
+    <color name="holo_green_light">#ff99cc00</color>
+    <!-- A light Holo shade of red -->
+    <color name="holo_red_light">#ffff4444</color>
+    <!-- A dark Holo shade of blue -->
+    <color name="holo_blue_dark">#ff0099cc</color>
+    <!-- A dark Holo shade of green -->
+    <color name="holo_green_dark">#ff669900</color>
+    <!-- A dark Holo shade of red -->
+    <color name="holo_red_dark">#ffcc0000</color>
+    <!-- A Holo shade of purple -->
+    <color name="holo_purple">#ffaa66cc</color>
+    <!-- A light Holo shade of orange -->
+    <color name="holo_orange_light">#ffffbb33</color>
+    <!-- A dark Holo shade of orange -->
+    <color name="holo_orange_dark">#ffff8800</color>
+    <!-- A really bright Holo shade of blue -->
+    <color name="holo_blue_bright">#ff00ddff</color>
+    <!-- A really bright Holo shade of gray -->
+    <color name="holo_gray_bright">#33CCCCCC</color>
+
+    <!-- Forward compatibility for Quantum-style theme colors -->
+    <eat-comment />
+
+    <color name="holo_primary_dark">#ff000000</color>
+    <color name="holo_primary">#ffe6e6e6</color>
+    <color name="holo_primary_light">#ffffffff</color>
+    <color name="holo_control_activated">@color/holo_blue_light</color>
+    <color name="holo_control_normal">#39cccccc</color>
+    <color name="holo_button_pressed">#59f0f0f0</color>
+    <color name="holo_button_normal">#bd292f34</color>
+
+    <color name="holo_light_primary_dark">#ff000000</color>
+    <color name="holo_light_primary">#ffe6e6e6</color>
+    <color name="holo_light_primary_light">#ffffffff</color>
+    <color name="holo_light_control_activated">@color/holo_control_activated</color>
+    <color name="holo_light_control_normal">#dacccccc</color>
+    <color name="holo_light_button_pressed">#66666666</color>
+    <color name="holo_light_button_normal">#b3cccccc</color>
+
+    <!-- Group buttons -->
+    <eat-comment />
+
+    <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
+    <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
+
+    <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
+    <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
+
+    <!-- Time picker -->
+    <eat-comment />
+
+    <color name="timepicker_default_background_holo_light">@color/white</color>
+    <color name="timepicker_default_background_holo_dark">#ff303030</color>
+
+    <color name="timepicker_default_text_color_holo_light">#8c8c8c</color>
+    <color name="timepicker_default_text_color_holo_dark">@color/white</color>
+
+    <color name="timepicker_default_disabled_color_holo_light">#7f000000</color>
+    <color name="timepicker_default_disabled_color_holo_dark">#7f08c8c8</color>
+
+    <color name="timepicker_default_ampm_selected_background_color_holo_light">@color/holo_blue_light</color>
+    <color name="timepicker_default_ampm_selected_background_color_holo_dark">@color/holo_blue_light</color>
+
+    <color name="timepicker_default_ampm_unselected_background_color_holo_light">@color/white</color>
+    <color name="timepicker_default_ampm_unselected_background_color_holo_dark">@color/transparent</color>
+</resources>
diff --git a/core/res/res/values/colors_legacy.xml b/core/res/res/values/colors_legacy.xml
new file mode 100644
index 0000000..48d4b42
--- /dev/null
+++ b/core/res/res/values/colors_legacy.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Colors specific to pre-Holo themes. -->
+<resources>
+
+    <!-- Highlight colors for the legacy themes -->
+    <eat-comment />
+
+    <color name="legacy_pressed_highlight">#fffeaa0c</color>
+    <color name="legacy_selected_highlight">#fff17a0a</color>
+    <color name="legacy_long_pressed_highlight">#ffffffff</color>
+
+    <!-- Forward compatibility for Quantum-style theme colors -->
+    <eat-comment />
+
+    <color name="legacy_primary_dark">#ff000000</color>
+    <color name="legacy_primary">#ffe6e6e6</color>
+    <color name="legacy_primary_light">#ffffffff</color>
+    <color name="legacy_control_activated">#ff90df25</color>
+    <color name="legacy_control_normal">#99ffffff</color>
+    <color name="legacy_button_pressed">#fffea50b</color>
+    <color name="legacy_button_normal">#f3dbdbdb</color>
+
+    <color name="legacy_light_primary_dark">@color/legacy_primary_dark</color>
+    <color name="legacy_light_primary">@color/legacy_primary</color>
+    <color name="legacy_light_primary_light">@color/legacy_primary_light</color>
+    <color name="legacy_light_control_activated">@color/legacy_control_activated</color>
+    <color name="legacy_light_control_normal">#99000000</color>
+    <color name="legacy_light_button_pressed">@color/legacy_button_pressed</color>
+    <color name="legacy_light_button_normal">@color/legacy_button_normal</color>
+</resources>
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index f8f192f..7171450 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -14,6 +14,7 @@
      limitations under the License.
 -->
 
+<!-- Colors specific to Quantum themes. -->
 <resources>
     <color name="background_quantum_dark">@color/black</color>
     <color name="background_quantum_light">@color/white</color>
@@ -40,6 +41,7 @@
     <color name="highlighted_text_quantum_light">#660097a7</color>
 
     <!-- Primary & accent colors -->
+    <eat-comment />
 
     <color name="quantum_red_100">#fff4c7c3</color>
     <color name="quantum_red_300">#ffe67c73</color>
@@ -98,6 +100,7 @@
     <color name="quantum_deep_orange_A400">#ffff1744</color>
 
     <!-- Neutral colors -->
+    <eat-comment />
 
     <color name="quantum_grey_50">#fffafafa</color>
     <color name="quantum_grey_100">#fff5f5f5</color>
@@ -117,6 +120,7 @@
     <color name="quantum_brown_700">#ff5d4037</color>
 
     <!-- Text & foreground colors -->
+    <eat-comment />
 
     <color name="primary_text_default_quantum_light">#de000000</color>
     <color name="secondary_text_quantum_light">#8a000000</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f919c9f..f39155b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1206,6 +1206,15 @@
          movement threshold where scrolling should begin. -->
     <dimen name="config_viewConfigurationTouchSlop">8dp</dimen>
 
+    <!-- Minimum velocity to initiate a fling, as measured in dips per second. -->
+    <dimen name="config_viewMinFlingVelocity">50dp</dimen>
+
+    <!-- Maximum velocity to initiate a fling, as measured in dips per second. -->
+    <dimen name="config_viewMaxFlingVelocity">8000dp</dimen>
+
+    <!-- Amount of time in ms the user needs to press the relevant key to bring up the global actions dialog -->
+    <integer name="config_globalActionsKeyTimeout">500</integer>
+
     <!-- Maximum number of grid columns permitted in the ResolverActivity
          used for picking activities to handle an intent. -->
     <integer name="config_maxResolverActivityColumns">2</integer>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5ccb05b..ec73b9f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2162,10 +2162,12 @@
   <public type="attr" name="windowAllowExitTransitionOverlap" />
   <public type="attr" name="windowAllowEnterTransitionOverlap" />
   <public type="attr" name="sessionService" />
+  <public type="attr" name="stackViewStyle" />
   <public type="attr" name="switchStyle" />
   <public type="attr" name="elevation" />
   <public type="attr" name="excludeId" />
   <public type="attr" name="excludeClass" />
+  <public type="attr" name="hideOnContentScroll" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
@@ -2180,15 +2182,25 @@
 
   <public-padding type="style" name="l_resource_pad" end="0x01030200" />
 
-  <public type="style" name="Widget.Holo.FragmentBreadCrumbs" />
-  <public type="style" name="Widget.Holo.Light.FragmentBreadCrumbs" />
-  <public type="style" name="Widget.DeviceDefault.FragmentBreadCrumbs" />
-  <public type="style" name="Widget.DeviceDefault.Light.FragmentBreadCrumbs" />
   <public type="style" name="Widget.FastScroll" />
+  <public type="style" name="Widget.StackView" />
+
   <public type="style" name="Widget.Holo.FastScroll" />
+  <public type="style" name="Widget.Holo.FragmentBreadCrumbs" />
+  <public type="style" name="Widget.Holo.StackView" />
+
+  <public type="style" name="Widget.Holo.Light.Button.Borderless" />
   <public type="style" name="Widget.Holo.Light.FastScroll" />
+  <public type="style" name="Widget.Holo.Light.FragmentBreadCrumbs" />
+  <public type="style" name="Widget.Holo.Light.StackView" />
+
   <public type="style" name="Widget.DeviceDefault.FastScroll" />
+  <public type="style" name="Widget.DeviceDefault.FragmentBreadCrumbs" />
+  <public type="style" name="Widget.DeviceDefault.StackView" />
+
   <public type="style" name="Widget.DeviceDefault.Light.FastScroll" />
+  <public type="style" name="Widget.DeviceDefault.Light.FragmentBreadCrumbs" />
+  <public type="style" name="Widget.DeviceDefault.Light.StackView" />
 
   <public type="style" name="TextAppearance.Quantum" />
   <public type="style" name="TextAppearance.Quantum.DialogWindowTitle" />
@@ -2265,7 +2277,6 @@
   <public type="style" name="Widget.Quantum.ActionButton" />
   <public type="style" name="Widget.Quantum.ActionButton.CloseMode" />
   <public type="style" name="Widget.Quantum.ActionButton.Overflow" />
-  <public type="style" name="Widget.Quantum.ActionButton.TextButton" />
   <public type="style" name="Widget.Quantum.ActionMode" />
   <public type="style" name="Widget.Quantum.AutoCompleteTextView" />
   <public type="style" name="Widget.Quantum.Button" />
@@ -2308,6 +2319,7 @@
   <public type="style" name="Widget.Quantum.ScrollView" />
   <public type="style" name="Widget.Quantum.SeekBar" />
   <public type="style" name="Widget.Quantum.SegmentedButton" />
+  <public type="style" name="Widget.Quantum.StackView" />
   <public type="style" name="Widget.Quantum.Spinner" />
   <public type="style" name="Widget.Quantum.Tab" />
   <public type="style" name="Widget.Quantum.TabWidget" />
@@ -2328,6 +2340,7 @@
   <public type="style" name="Widget.Quantum.Light.ActionMode" />
   <public type="style" name="Widget.Quantum.Light.AutoCompleteTextView" />
   <public type="style" name="Widget.Quantum.Light.Button" />
+  <public type="style" name="Widget.Quantum.Light.Button.Borderless" />
   <public type="style" name="Widget.Quantum.Light.Button.Borderless.Small" />
   <public type="style" name="Widget.Quantum.Light.Button.Inset" />
   <public type="style" name="Widget.Quantum.Light.Button.Small" />
@@ -2368,6 +2381,7 @@
   <public type="style" name="Widget.Quantum.Light.ScrollView" />
   <public type="style" name="Widget.Quantum.Light.SeekBar" />
   <public type="style" name="Widget.Quantum.Light.SegmentedButton" />
+  <public type="style" name="Widget.Quantum.Light.StackView" />
   <public type="style" name="Widget.Quantum.Light.Spinner" />
   <public type="style" name="Widget.Quantum.Light.Tab" />
   <public type="style" name="Widget.Quantum.Light.TabWidget" />
@@ -2376,12 +2390,6 @@
   <public type="style" name="Widget.Quantum.Light.WebTextView" />
   <public type="style" name="Widget.Quantum.Light.WebView" />
 
-  <public type="style" name="Widget.Quantum.Button.Paper" />
-  <public type="style" name="Widget.Quantum.Button.Paper.Color" />
-
-  <public type="style" name="Widget.Quantum.Light.Button.Paper" />
-  <public type="style" name="Widget.Quantum.Light.Button.Paper.Color" />
-
   <public type="style" name="TextAppearance.Quantum.Display4" />
   <public type="style" name="TextAppearance.Quantum.Display3" />
   <public type="style" name="TextAppearance.Quantum.Display2" />
@@ -2395,8 +2403,6 @@
   <public type="style" name="TextAppearance.Quantum.Menu" />
   <public type="style" name="TextAppearance.Quantum.Button" />
 
-  <public type="style" name="Widget.Holo.Light.Button.Borderless" />
-
   <public-padding type="interpolator" name="l_resource_pad" end="0x010c0010" />
 
   <!-- An interpolator which accelerates fast but decelerates slowly. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 57b2c01..97400b2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -454,6 +454,12 @@
     <!-- Label for the Android system components when they are shown to the user. -->
     <string name="android_system_label">Android System</string>
 
+    <!-- Label for the user owner in the intent forwarding app. -->
+    <string name="user_owner_label">Personal</string>
+
+    <!-- Label for a corporate profile in the intent forwarding app. -->
+    <string name="managed_profile_label">Work</string>
+
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_costMoney">Services that cost you money</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index fc0fccc..891265f 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -169,6 +169,12 @@
         <item name="windowExitAnimation">@anim/input_method_exit</item>
     </style>
 
+    <!-- Window animations that are applied to voice interaction overlay windows. -->
+    <style name="Animation.VoiceInteractionSession">
+        <item name="windowEnterAnimation">@anim/input_method_enter</item>
+        <item name="windowExitAnimation">@anim/input_method_exit</item>
+    </style>
+
     <!-- Special optional fancy IM animations. @hide -->
     <style name="Animation.InputMethodFancy">
         <item name="windowEnterAnimation">@anim/input_method_fancy_enter</item>
@@ -397,6 +403,11 @@
         <item name="android:disabledAlpha">?android:attr/disabledAlpha</item>
     </style>
 
+    <style name="Widget.StackView">
+        <item name="android:resOutColor">@android:color/holo_blue_light</item>
+        <item name="android:clickColor">@android:color/holo_blue_light</item>
+    </style>
+
     <style name="Widget.ProgressBar">
         <item name="android:indeterminateOnly">true</item>
         <item name="android:indeterminateDrawable">@android:drawable/progress_medium_white</item>
@@ -1609,11 +1620,6 @@
         <item name="android:minWidth">64dip</item>
     </style>
 
-    <style name="Widget.Holo.StackView">
-        <item name="android:resOutColor">@android:color/holo_blue_light</item>
-        <item name="android:clickColor">@android:color/holo_blue_light</item>
-    </style>
-
     <style name="Widget.Holo.Button.Borderless">
         <item name="android:background">?android:attr/selectableItemBackground</item>
         <item name="android:paddingStart">4dip</item>
@@ -1645,6 +1651,11 @@
         <item name="android:minHeight">48dip</item>
     </style>
 
+    <style name="Widget.Holo.StackView">
+        <item name="android:resOutColor">@android:color/holo_blue_light</item>
+        <item name="android:clickColor">@android:color/holo_blue_light</item>
+    </style>
+
     <style name="Holo.ButtonBar" parent="ButtonBar">
         <item name="android:paddingTop">0dip</item>
         <item name="android:paddingStart">0dip</item>
@@ -2099,6 +2110,11 @@
         <item name="android:minHeight">48dip</item>
     </style>
 
+    <style name="Widget.Holo.Light.StackView">
+        <item name="android:resOutColor">@android:color/holo_blue_light</item>
+        <item name="android:clickColor">@android:color/holo_blue_light</item>
+    </style>
+
     <style name="Holo.Light.ButtonBar" parent="Holo.ButtonBar">
     </style>
 
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 629b2b7..60e06ce 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -72,7 +72,7 @@
     <style name="Widget.DeviceDefault.PopupMenu" parent="Widget.Quantum.PopupMenu"/>
     <style name="Widget.DeviceDefault.ActionButton" parent="Widget.Quantum.ActionButton"/>
     <style name="Widget.DeviceDefault.ActionButton.Overflow" parent="Widget.Quantum.ActionButton.Overflow"/>
-    <style name="Widget.DeviceDefault.ActionButton.TextButton" parent="Widget.Quantum.ActionButton.TextButton"/>
+    <style name="Widget.DeviceDefault.ActionButton.TextButton" parent="Widget.Quantum.ActionButton"/>
     <style name="Widget.DeviceDefault.ActionMode" parent="Widget.Quantum.ActionMode"/>
     <style name="Widget.DeviceDefault.ActionButton.CloseMode" parent="Widget.Quantum.ActionButton.CloseMode"/>
     <style name="Widget.DeviceDefault.ActionBar" parent="Widget.Quantum.ActionBar"/>
@@ -97,6 +97,7 @@
     <style name="Widget.DeviceDefault.ImageWell" parent="Widget.Quantum.ImageWell"/>
     <style name="Widget.DeviceDefault.KeyboardView" parent="Widget.Quantum.KeyboardView"/>
     <style name="Widget.DeviceDefault.ListView.White" parent="Widget.Quantum.ListView.White"/>
+    <style name="Widget.DeviceDefault.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton" />
     <style name="Widget.DeviceDefault.NumberPicker" parent="Widget.Quantum.NumberPicker"/>
     <style name="Widget.DeviceDefault.PreferenceFrameLayout" parent="Widget.Quantum.PreferenceFrameLayout"/>
     <style name="Widget.DeviceDefault.ProgressBar.Inverse" parent="Widget.Quantum.ProgressBar.Inverse"/>
@@ -114,11 +115,13 @@
     <style name="Widget.DeviceDefault.TextSuggestionsPopupWindow" parent="Widget.Quantum.TextSuggestionsPopupWindow"/>
     <style name="Widget.DeviceDefault.TextView.ListSeparator" parent="Widget.Quantum.TextView.ListSeparator"/>
     <style name="Widget.DeviceDefault.TimePicker" parent="Widget.Quantum.TimePicker"/>
+
     <style name="Widget.DeviceDefault.Light" parent="Widget.Quantum.Light"/>
     <style name="Widget.DeviceDefault.Light.Button" parent="Widget.Quantum.Light.Button"/>
     <style name="Widget.DeviceDefault.Light.Button.Small" parent="Widget.Quantum.Light.Button.Small"/>
     <style name="Widget.DeviceDefault.Light.Button.Inset" parent="Widget.Quantum.Light.Button.Inset"/>
     <style name="Widget.DeviceDefault.Light.Button.Toggle" parent="Widget.Quantum.Light.Button.Toggle"/>
+    <style name="Widget.DeviceDefault.Light.StackView" parent="Widget.Quantum.Light.StackView"/>
     <style name="Widget.DeviceDefault.Light.TextView" parent="Widget.Quantum.Light.TextView"/>
     <style name="Widget.DeviceDefault.Light.CheckedTextView" parent="Widget.Quantum.Light.CheckedTextView"/>
     <style name="Widget.DeviceDefault.Light.AutoCompleteTextView" parent="Widget.Quantum.Light.AutoCompleteTextView"/>
@@ -131,6 +134,7 @@
     <style name="Widget.DeviceDefault.Light.GridView" parent="Widget.Quantum.Light.GridView"/>
     <style name="Widget.DeviceDefault.Light.ImageButton" parent="Widget.Quantum.Light.ImageButton"/>
     <style name="Widget.DeviceDefault.Light.ListView" parent="Widget.Quantum.Light.ListView"/>
+    <style name="Widget.DeviceDefault.Light.MediaRouteButton" parent="Widget.Quantum.Light.MediaRouteButton" />
     <style name="Widget.DeviceDefault.Light.PopupWindow" parent="Widget.Quantum.Light.PopupWindow"/>
     <style name="Widget.DeviceDefault.Light.ProgressBar" parent="Widget.Quantum.Light.ProgressBar"/>
     <style name="Widget.DeviceDefault.Light.ProgressBar.Horizontal" parent="Widget.Quantum.Light.ProgressBar.Horizontal"/>
@@ -195,7 +199,6 @@
     <style name="Widget.DeviceDefault.Light.TimePicker" parent="Widget.Quantum.Light.TimePicker"/>
     <style name="Widget.DeviceDefault.Light.TextSuggestionsPopupWindow" parent="Widget.Quantum.Light.TextSuggestionsPopupWindow"/>
 
-
     <!-- Text Appearance Styles -->
     <style name="TextAppearance.DeviceDefault" parent="TextAppearance.Quantum"/>
     <style name="TextAppearance.DeviceDefault.Inverse" parent="TextAppearance.Quantum.Inverse"/>
@@ -207,6 +210,8 @@
     <style name="TextAppearance.DeviceDefault.Small.Inverse" parent="TextAppearance.Quantum.Small.Inverse"/>
     <style name="TextAppearance.DeviceDefault.SearchResult.Title" parent="TextAppearance.Quantum.SearchResult.Title"/>
     <style name="TextAppearance.DeviceDefault.SearchResult.Subtitle" parent="TextAppearance.Quantum.SearchResult.Subtitle"/>
+    <style name="TextAppearance.DeviceDefault.TimePicker.TimeLabel" parent="TextAppearance.Quantum.TimePicker.TimeLabel"/>
+    <style name="TextAppearance.DeviceDefault.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.TimePicker.AmPmLabel"/>
     <style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Quantum.Widget"/>
     <style name="TextAppearance.DeviceDefault.Widget.Button" parent="TextAppearance.Quantum.Widget.Button"/>
     <style name="TextAppearance.DeviceDefault.Widget.IconMenu.Item" parent="TextAppearance.Quantum.Widget.IconMenu.Item"/>
@@ -235,20 +240,6 @@
     <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
     <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse"/>
     <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Menu" parent="TextAppearance.Quantum.Widget.ActionBar.Menu"/>
-    <style name="TextAppearance.DeviceDefault.Light" parent="TextAppearance.Quantum.Light"/>
-    <style name="TextAppearance.DeviceDefault.Light.Inverse" parent="TextAppearance.Quantum.Light.Inverse"/>
-    <style name="TextAppearance.DeviceDefault.Light.Large" parent="TextAppearance.Quantum.Light.Large"/>
-    <style name="TextAppearance.DeviceDefault.Light.Large.Inverse" parent="TextAppearance.Quantum.Light.Large.Inverse"/>
-    <style name="TextAppearance.DeviceDefault.Light.Medium" parent="TextAppearance.Quantum.Light.Medium"/>
-    <style name="TextAppearance.DeviceDefault.Light.Medium.Inverse" parent="TextAppearance.Quantum.Light.Medium.Inverse"/>
-    <style name="TextAppearance.DeviceDefault.Light.SearchResult.Subtitle" parent="TextAppearance.Quantum.Light.SearchResult.Subtitle"/>
-    <style name="TextAppearance.DeviceDefault.Light.SearchResult.Title" parent="TextAppearance.Quantum.Light.SearchResult.Title"/>
-    <style name="TextAppearance.DeviceDefault.Light.Small" parent="TextAppearance.Quantum.Light.Small"/>
-    <style name="TextAppearance.DeviceDefault.Light.Small.Inverse" parent="TextAppearance.Quantum.Light.Small.Inverse"/>
-    <style name="TextAppearance.DeviceDefault.Light.Widget.Button" parent="TextAppearance.Quantum.Light.Widget.Button"/>
-    <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Large" parent="TextAppearance.Quantum.Light.Widget.PopupMenu.Large"/>
-    <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Small" parent="TextAppearance.Quantum.Light.Widget.PopupMenu.Small"/>
-
 
     <!-- Preference Styles -->
     <style name="Preference.DeviceDefault" parent="Preference.Quantum"/>
@@ -262,7 +253,6 @@
     <style name="Preference.DeviceDefault.RingtonePreference" parent="Preference.Quantum.RingtonePreference"/>
     <style name="Preference.DeviceDefault.SwitchPreference" parent="Preference.Quantum.SwitchPreference"/>
 
-
     <!-- AlertDialog Styles -->
     <style name="AlertDialog.DeviceDefault" parent="AlertDialog.Quantum"/>
     <style name="AlertDialog.DeviceDefault.Light" parent="AlertDialog.Quantum.Light"/>
@@ -271,32 +261,20 @@
     <style name="Animation.DeviceDefault.Activity" parent="Animation.Quantum.Activity"/>
     <style name="Animation.DeviceDefault.Dialog" parent="Animation.Quantum.Dialog"/>
 
-
     <!-- DialogWindowTitle Styles -->
     <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Quantum"/>
     <style name="DialogWindowTitle.DeviceDefault.Light" parent="DialogWindowTitle.Quantum.Light"/>
 
-
     <!-- WindowTitle Styles -->
     <style name="WindowTitle.DeviceDefault" parent="WindowTitle.Quantum"/>
     <style name="WindowTitleBackground.DeviceDefault" parent="WindowTitleBackground.Quantum"/>
 
-
     <!-- Other Styles -->
     <style name="DeviceDefault.ButtonBar" parent="Widget.Quantum.ButtonBar"/>
     <style name="DeviceDefault.ButtonBar.AlertDialog" parent="Widget.Quantum.ButtonBar.AlertDialog"/>
     <style name="DeviceDefault.SegmentedButton" parent="Widget.Quantum.SegmentedButton"/>
+
     <style name="DeviceDefault.Light.ButtonBar" parent="Widget.Quantum.Light.ButtonBar"/>
     <style name="DeviceDefault.Light.ButtonBar.AlertDialog" parent="Widget.Quantum.Light.ButtonBar.AlertDialog"/>
     <style name="DeviceDefault.Light.SegmentedButton" parent="Widget.Quantum.Light.SegmentedButton"/>
-
-    <style name="Widget.DeviceDefault.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton" />
-    <style name="Widget.DeviceDefault.Light.MediaRouteButton" parent="Widget.Quantum.Light.MediaRouteButton" />
-
-    <style name="TextAppearance.DeviceDefault.TimePicker.TimeLabel" parent="TextAppearance.Quantum.TimePicker.TimeLabel"/>
-    <style name="TextAppearance.DeviceDefault.Light.TimePicker.TimeLabel" parent="TextAppearance.Quantum.Light.TimePicker.TimeLabel"/>
-    <style name="TextAppearance.DeviceDefault.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.TimePicker.AmPmLabel"/>
-    <style name="TextAppearance.DeviceDefault.Light.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.Light.TimePicker.AmPmLabel"/>
-    <style name="Theme.DeviceDefault.Dialog.TimePicker" parent="Theme.Quantum.Dialog.TimePicker"/>
-    <style name="Theme.DeviceDefault.Light.Dialog.TimePicker" parent="Theme.Quantum.Light.Dialog.TimePicker"/>
 </resources>
diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml
index 52d90bc..bdaa49d 100644
--- a/core/res/res/values/styles_micro.xml
+++ b/core/res/res/values/styles_micro.xml
@@ -14,21 +14,44 @@
      limitations under the License.
 -->
 <resources>
+    <style name="AlertDialog.Micro" parent="AlertDialog.Holo.Light">
+        <item name="layout">@layout/alert_dialog_micro</item>
+    </style>
+
+    <style name="DialogWindowTitle.Micro">
+        <item name="maxLines">1</item>
+        <item name="scrollHorizontally">true</item>
+        <item name="textAppearance">@style/TextAppearance.Micro.DialogWindowTitle</item>
+    </style>
+
+    <style name="TextAppearance.Micro" parent="TextAppearance.Holo">
+        <item name="textSize">20sp</item>
+        <item name="fontFamily">sans-serif-condensed-light</item>
+        <item name="textColor">@color/micro_text_light</item>
+    </style>
+
+    <style name="TextAppearance.Micro.DialogWindowTitle" parent="TextAppearance.Holo.DialogWindowTitle">
+        <item name="textSize">20sp</item>
+        <item name="fontFamily">sans-serif-condensed-light</item>
+        <item name="textColor">@color/micro_text_light</item>
+    </style>
+
     <style name="Widget.Micro" parent="Widget.Holo" />
 
     <style name="Widget.Micro.TextView">
-        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="fontFamily">sans-serif-condensed</item>
     </style>
 
     <style name="Widget.Micro.NumberPicker">
-        <item name="android:internalLayout">@android:layout/number_picker_with_selector_wheel_micro</item>
-        <item name="android:solidColor">@android:color/transparent</item>
-        <item name="android:selectionDivider">@android:drawable/numberpicker_selection_divider</item>
-        <item name="android:selectionDividerHeight">0dip</item>
-        <item name="android:selectionDividersDistance">104dip</item>
-        <item name="android:internalMinWidth">64dip</item>
-        <item name="android:internalMaxHeight">180dip</item>
-        <item name="virtualButtonPressedDrawable">?android:attr/selectableItemBackground</item>
-        <item name="android:descendantFocusability">blocksDescendants</item>
+        <item name="internalLayout">@layout/number_picker_with_selector_wheel_micro</item>
+        <item name="solidColor">@color/transparent</item>
+        <item name="selectionDivider">@drawable/numberpicker_selection_divider</item>
+        <item name="selectionDividerHeight">0dip</item>
+        <item name="selectionDividersDistance">104dip</item>
+        <item name="internalMinWidth">64dip</item>
+        <item name="internalMaxHeight">180dip</item>
+        <item name="virtualButtonPressedDrawable">?attr/selectableItemBackground</item>
+        <item name="descendantFocusability">blocksDescendants</item>
     </style>
+
 </resources>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 57f2443..7679420 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -351,40 +351,6 @@
         <item name="textStyle">bold</item>
     </style>
 
-    <!-- Light text styles -->
-    <style name="TextAppearance.Quantum.Light" parent="TextAppearance.Quantum"/>
-    <style name="TextAppearance.Quantum.Light.Inverse" parent="TextAppearance.Quantum.Inverse"/>
-    <style name="TextAppearance.Quantum.Light.Large" parent="TextAppearance.Quantum.Large"/>
-    <style name="TextAppearance.Quantum.Light.Large.Inverse" parent="TextAppearance.Quantum.Large.Inverse"/>
-    <style name="TextAppearance.Quantum.Light.Medium" parent="TextAppearance.Quantum.Medium"/>
-    <style name="TextAppearance.Quantum.Light.Medium.Inverse" parent="TextAppearance.Quantum.Medium.Inverse"/>
-    <style name="TextAppearance.Quantum.Light.Small" parent="TextAppearance.Quantum.Small"/>
-    <style name="TextAppearance.Quantum.Light.Small.Inverse" parent="TextAppearance.Quantum.Small.Inverse"/>
-    <style name="TextAppearance.Quantum.Light.SearchResult" parent="TextAppearance.Quantum.SearchResult"/>
-    <style name="TextAppearance.Quantum.Light.SearchResult.Title" parent="TextAppearance.Quantum.SearchResult.Title"/>
-    <style name="TextAppearance.Quantum.Light.SearchResult.Subtitle" parent="TextAppearance.Quantum.SearchResult.Subtitle"/>
-    <style name="TextAppearance.Quantum.Light.Widget" parent="TextAppearance.Quantum.Widget"/>
-    <style name="TextAppearance.Quantum.Light.Widget.Button" parent="TextAppearance.Quantum.Widget.Button"/>
-    <style name="TextAppearance.Quantum.Light.Widget.EditText" parent="TextAppearance.Quantum.Widget.EditText"/>
-    <style name="TextAppearance.Quantum.Light.Widget.Switch" parent="TextAppearance.Quantum.Widget.Switch"/>
-    <style name="TextAppearance.Quantum.Light.Widget.PopupMenu" parent="TextAppearance.Quantum.Widget.PopupMenu"/>
-    <style name="TextAppearance.Quantum.Light.Widget.PopupMenu.Large" parent="TextAppearance.Quantum.Widget.PopupMenu.Large"/>
-    <style name="TextAppearance.Quantum.Light.Widget.PopupMenu.Small" parent="TextAppearance.Quantum.Widget.PopupMenu.Small"/>
-    <style name="TextAppearance.Quantum.Light.Widget.DropDownHint" parent="TextAppearance.Quantum.Widget.DropDownHint"/>
-    <style name="TextAppearance.Quantum.Light.Widget.ActionMode.Title" parent="TextAppearance.Quantum.Widget.ActionMode.Title"/>
-    <style name="TextAppearance.Quantum.Light.Widget.ActionMode.Subtitle" parent="TextAppearance.Quantum.Widget.ActionMode.Subtitle"/>
-    <style name="TextAppearance.Quantum.Light.WindowTitle" parent="TextAppearance.Quantum.WindowTitle"/>
-    <style name="TextAppearance.Quantum.Light.DialogWindowTitle" parent="TextAppearance.Quantum.DialogWindowTitle"/>
-    <style name="TextAppearance.Quantum.Light.CalendarViewWeekDayView" parent="TextAppearance.Quantum.CalendarViewWeekDayView"/>
-
-    <style name="TextAppearance.Quantum.Light.TimePicker.TimeLabel" parent="TextAppearance.Quantum.TimePicker.TimeLabel">
-        <item name="textColor">?attr/textColorSecondary</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Light.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.TimePicker.AmPmLabel">
-        <item name="textColor">?attr/textColorSecondary</item>
-    </style>
-
     <!-- Widget Styles -->
 
     <style name="Quantum"/>
@@ -406,16 +372,6 @@
         <item name="minWidth">48dip</item>
     </style>
 
-    <!-- Bordered paper button -->
-    <style name="Widget.Quantum.Button.Paper">
-        <!-- TODO: Specify pressed state animation. -->
-    </style>
-
-    <!-- Bordered paper button with color -->
-    <style name="Widget.Quantum.Button.Paper.Color">
-        <item name="background">@drawable/btn_color_quantum</item>
-    </style>
-
     <!-- Borderless ink button -->
     <style name="Widget.Quantum.Button.Borderless">
         <item name="background">@drawable/btn_borderless_quantum</item>
@@ -427,11 +383,6 @@
         <item name="minWidth">48dip</item>
     </style>
 
-    <!-- Borderless paper button -->
-    <style name="Widget.Quantum.Button.Borderless.Paper">
-        <!-- TODO: Specify pressed state animation. -->
-    </style>
-
     <style name="Widget.Quantum.Button.Inset">
         <item name="background">@drawable/button_inset</item>
     </style>
@@ -743,8 +694,6 @@
         <item name="scaleType">center</item>
     </style>
 
-    <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>
         <item name="paddingStart">16dip</item>
@@ -820,11 +769,8 @@
     <style name="Widget.Quantum.Light" parent="Widget.Quantum"/>
     <style name="Widget.Quantum.Light.Button" parent="Widget.Quantum.Button"/>
     <style name="Widget.Quantum.Light.Button.Small" parent="Widget.Quantum.Button.Small"/>
-    <style name="Widget.Quantum.Light.Button.Paper" parent="Widget.Quantum.Button.Paper"/>
-    <style name="Widget.Quantum.Light.Button.Paper.Color" parent="Widget.Quantum.Button.Paper.Color"/>
     <style name="Widget.Quantum.Light.Button.Borderless" parent="Widget.Quantum.Button.Borderless"/>
     <style name="Widget.Quantum.Light.Button.Borderless.Small" parent="Widget.Quantum.Button.Borderless.Small"/>
-    <style name="Widget.Quantum.Light.Button.Borderless.Paper" parent="Widget.Quantum.Button.Borderless.Paper"/>
     <style name="Widget.Quantum.Light.Button.Inset" parent="Widget.Quantum.Button.Inset"/>
 
     <style name="Widget.Quantum.Light.Button.Toggle">
@@ -842,6 +788,7 @@
         <item name="background">@drawable/btn_group_holo_light</item>
     </style>
 
+    <style name="Widget.Quantum.Light.StackView" parent="Widget.Quantum.StackView"/>
     <style name="Widget.Quantum.Light.TextView" parent="Widget.Quantum.TextView"/>
     <style name="Widget.Quantum.Light.TextView.ListSeparator" parent="Widget.Quantum.TextView.ListSeparator"/>
     <style name="Widget.Quantum.Light.TextView.SpinnerItem" parent="Widget.Quantum.TextView.SpinnerItem"/>
@@ -861,7 +808,7 @@
     <style name="Widget.Quantum.Light.CompoundButton.Star" parent="Widget.Quantum.CompoundButton.Star"/>
 
     <style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch">
-        <item name="switchTextAppearance">@style/TextAppearance.Quantum.Light.Widget.Switch</item>
+        <item name="switchTextAppearance">@style/TextAppearance.Quantum.Widget.Switch</item>
     </style>
 
     <style name="Widget.Quantum.Light.ListView.DropDown" parent="Widget.Quantum.ListView.DropDown"/>
@@ -880,7 +827,7 @@
         <item name="unfocusedMonthDateColor">#7F08002B</item>
         <item name="weekNumberColor">#7F080021</item>
         <item name="weekSeparatorLineColor">#7F08002A</item>
-        <item name="weekDayTextAppearance">@style/TextAppearance.Quantum.Light.CalendarViewWeekDayView</item>
+        <item name="weekDayTextAppearance">@style/TextAppearance.Quantum.CalendarViewWeekDayView</item>
     </style>
 
     <style name="Widget.Quantum.Light.NumberPicker" parent="Widget.Quantum.NumberPicker"/>
@@ -1058,7 +1005,7 @@
     </style>
 
     <style name="DialogWindowTitle.Quantum.Light">
-        <item name="textAppearance">@style/TextAppearance.Quantum.Light.DialogWindowTitle</item>
+        <item name="textAppearance">@style/TextAppearance.Quantum.DialogWindowTitle</item>
     </style>
 
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d4ac74a..6bcbbce 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -232,7 +232,6 @@
   <java-symbol type="attr" name="preferenceFrameLayoutStyle" />
   <java-symbol type="attr" name="searchDialogTheme" />
   <java-symbol type="attr" name="searchViewSearchIcon" />
-  <java-symbol type="attr" name="stackViewStyle" />
   <java-symbol type="attr" name="textAppearanceAutoCorrectionSuggestion" />
   <java-symbol type="attr" name="textAppearanceEasyCorrectSuggestion" />
   <java-symbol type="attr" name="textAppearanceMisspelledSuggestion" />
@@ -328,6 +327,8 @@
   <java-symbol type="dimen" name="accessibility_touch_slop" />
   <java-symbol type="dimen" name="config_prefDialogWidth" />
   <java-symbol type="dimen" name="config_viewConfigurationTouchSlop" />
+  <java-symbol type="dimen" name="config_viewMinFlingVelocity" />
+  <java-symbol type="dimen" name="config_viewMaxFlingVelocity" />
   <java-symbol type="dimen" name="default_app_widget_padding_bottom" />
   <java-symbol type="dimen" name="default_app_widget_padding_left" />
   <java-symbol type="dimen" name="default_app_widget_padding_right" />
@@ -1197,6 +1198,7 @@
   <java-symbol type="layout" name="transient_notification" />
   <java-symbol type="layout" name="volume_adjust" />
   <java-symbol type="layout" name="volume_adjust_item" />
+  <java-symbol type="layout" name="voice_interaction_session" />
   <java-symbol type="layout" name="web_text_view_dropdown" />
   <java-symbol type="layout" name="webview_find" />
   <java-symbol type="layout" name="webview_select_singlechoice" />
@@ -1268,6 +1270,7 @@
   <java-symbol type="style" name="TextAppearance.SlidingTabNormal" />
   <java-symbol type="style" name="Theme.DeviceDefault.Dialog.NoFrame" />
   <java-symbol type="style" name="Theme.IconMenu" />
+  <java-symbol type="style" name="Theme.DeviceDefault.VoiceInteractionSession" />
 
   <java-symbol type="attr" name="mediaRouteButtonStyle" />
   <java-symbol type="attr" name="externalRouteEnabledDrawable" />
@@ -1624,6 +1627,7 @@
   <java-symbol type="string" name="wifi_display_notification_connected_message" />
   <java-symbol type="string" name="wifi_display_notification_disconnect" />
   <java-symbol type="style" name="Theme.Dialog.AppError" />
+  <java-symbol type="style" name="Theme.Micro.Dialog.Alert" />
   <java-symbol type="style" name="Theme.Toast" />
   <java-symbol type="xml" name="storage_list" />
   <java-symbol type="bool" name="config_dreamsSupported" />
@@ -1647,6 +1651,7 @@
   <java-symbol type="id" name="resolver_list" />
   <java-symbol type="id" name="button_once" />
   <java-symbol type="id" name="button_always" />
+  <java-symbol type="integer" name="config_globalActionsKeyTimeout" />
   <java-symbol type="integer" name="config_maxResolverActivityColumns" />
   <java-symbol type="array" name="config_notificationScorers" />
 
@@ -1859,5 +1864,9 @@
   <java-symbol type="id" name="icon_frame" />
   <java-symbol type="style" name="Animation.VolumePanel" />
   <java-symbol type="transition" name="no_transition" />
+  <java-symbol type="array" name="system_theme_sdks" />
+  <java-symbol type="array" name="system_theme_styles" />
+  <java-symbol type="array" name="system_theme_dialog_styles" />
+  <java-symbol type="array" name="system_theme_ime_styles" />
 
 </resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 7b3d5e3..e99f64f 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -53,6 +53,14 @@
         <item name="colorMultiSelectHighlight">@color/legacy_selected_highlight</item>
         <item name="colorActivatedHighlight">@color/legacy_selected_highlight</item>
 
+        <item name="colorPrimaryDark">@color/legacy_primary_dark</item>
+        <item name="colorPrimary">@color/legacy_primary</item>
+        <item name="colorPrimaryLight">@color/legacy_primary_light</item>
+        <item name="colorControlActivated">@color/legacy_control_activated</item>
+        <item name="colorControlNormal">@color/legacy_control_normal</item>
+        <item name="colorButtonPressed">@color/legacy_button_pressed</item>
+        <item name="colorButtonNormal">@color/legacy_button_normal</item>
+
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
@@ -437,6 +445,14 @@
         <item name="colorBackground">@android:color/background_light</item>
         <item name="colorForeground">@color/bright_foreground_light</item>
         <item name="colorForegroundInverse">@android:color/bright_foreground_light_inverse</item>
+
+        <item name="colorPrimaryDark">@color/legacy_light_primary_dark</item>
+        <item name="colorPrimary">@color/legacy_light_primary</item>
+        <item name="colorPrimaryLight">@color/legacy_light_primary_light</item>
+        <item name="colorControlActivated">@color/legacy_light_control_activated</item>
+        <item name="colorControlNormal">@color/legacy_light_control_normal</item>
+        <item name="colorButtonPressed">@color/legacy_light_button_pressed</item>
+        <item name="colorButtonNormal">@color/legacy_light_button_normal</item>
         
         <item name="textColorPrimary">@android:color/primary_text_light</item>
         <item name="textColorSecondary">@android:color/secondary_text_light</item>
@@ -789,6 +805,14 @@
         <item name="android:imeExtractExitAnimation">@android:anim/input_method_extract_exit</item>
     </style>
 
+    <!-- Default theme for voice interaction, which is used by the
+         {@link android.service.voice.VoiceInteractionSession} class.
+         this inherits from Theme.Panel, but sets up appropriate animations
+         and a few custom attributes. -->
+    <style name="Theme.VoiceInteractionSession" parent="Theme.Panel">
+        <item name="android:windowAnimationStyle">@android:style/Animation.VoiceInteractionSession</item>
+    </style>
+
     <!-- Default theme for holo style input methods, which is used by the
          {@link android.inputmethodservice.InputMethodService} class.
          this inherits from Theme.Panel, but sets up IME appropriate animations
@@ -937,6 +961,14 @@
         <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
         <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
 
+        <item name="colorPrimaryDark">@color/holo_primary_dark</item>
+        <item name="colorPrimary">@color/holo_primary</item>
+        <item name="colorPrimaryLight">@color/holo_primary_light</item>
+        <item name="colorControlActivated">@color/holo_control_activated</item>
+        <item name="colorControlNormal">@color/holo_control_normal</item>
+        <item name="colorButtonPressed">@color/holo_button_pressed</item>
+        <item name="colorButtonNormal">@color/holo_button_normal</item>
+
         <!-- Text styles -->
         <item name="textAppearance">@android:style/TextAppearance.Holo</item>
         <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
@@ -1268,6 +1300,14 @@
         <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
         <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
 
+        <item name="colorPrimaryDark">@color/holo_light_primary_dark</item>
+        <item name="colorPrimary">@color/holo_light_primary</item>
+        <item name="colorPrimaryLight">@color/holo_light_primary_light</item>
+        <item name="colorControlActivated">@color/holo_light_control_activated</item>
+        <item name="colorControlNormal">@color/holo_light_control_normal</item>
+        <item name="colorButtonPressed">@color/holo_light_button_pressed</item>
+        <item name="colorButtonNormal">@color/holo_light_button_normal</item>
+
         <!-- Text styles -->
         <item name="textAppearance">@android:style/TextAppearance.Holo.Light</item>
         <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Light.Inverse</item>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 0ce5094..dbc3d9e 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -51,139 +51,139 @@
           -->
     <style name="Theme.DeviceDefault" parent="Theme.Quantum" >
         <!-- Text styles -->
-        <item name="textAppearance">@android:style/TextAppearance.DeviceDefault</item>
-        <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Inverse</item>
+        <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>
+        <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>
 
-        <item name="textAppearanceLarge">@android:style/TextAppearance.DeviceDefault.Large</item>
-        <item name="textAppearanceMedium">@android:style/TextAppearance.DeviceDefault.Medium</item>
-        <item name="textAppearanceSmall">@android:style/TextAppearance.DeviceDefault.Small</item>
-        <item name="textAppearanceLargeInverse">@android:style/TextAppearance.DeviceDefault.Large.Inverse</item>
-        <item name="textAppearanceMediumInverse">@android:style/TextAppearance.DeviceDefault.Medium.Inverse</item>
-        <item name="textAppearanceSmallInverse">@android:style/TextAppearance.DeviceDefault.Small.Inverse</item>
-        <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.DeviceDefault.SearchResult.Title</item>
-        <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.DeviceDefault.SearchResult.Subtitle</item>
+        <item name="textAppearanceLarge">@style/TextAppearance.DeviceDefault.Large</item>
+        <item name="textAppearanceMedium">@style/TextAppearance.DeviceDefault.Medium</item>
+        <item name="textAppearanceSmall">@style/TextAppearance.DeviceDefault.Small</item>
+        <item name="textAppearanceLargeInverse">@style/TextAppearance.DeviceDefault.Large.Inverse</item>
+        <item name="textAppearanceMediumInverse">@style/TextAppearance.DeviceDefault.Medium.Inverse</item>
+        <item name="textAppearanceSmallInverse">@style/TextAppearance.DeviceDefault.Small.Inverse</item>
+        <item name="textAppearanceSearchResultTitle">@style/TextAppearance.DeviceDefault.SearchResult.Title</item>
+        <item name="textAppearanceSearchResultSubtitle">@style/TextAppearance.DeviceDefault.SearchResult.Subtitle</item>
 
-        <item name="textAppearanceButton">@android:style/TextAppearance.DeviceDefault.Widget.Button</item>
+        <item name="textAppearanceButton">@style/TextAppearance.DeviceDefault.Widget.Button</item>
 
-        <item name="textAppearanceLargePopupMenu">@android:style/TextAppearance.DeviceDefault.Widget.PopupMenu.Large</item>
-        <item name="textAppearanceSmallPopupMenu">@android:style/TextAppearance.DeviceDefault.Widget.PopupMenu.Small</item>
+        <item name="textAppearanceLargePopupMenu">@style/TextAppearance.DeviceDefault.Widget.PopupMenu.Large</item>
+        <item name="textAppearanceSmallPopupMenu">@style/TextAppearance.DeviceDefault.Widget.PopupMenu.Small</item>
 
         <!-- Button styles -->
-        <item name="buttonStyle">@android:style/Widget.DeviceDefault.Button</item>
+        <item name="buttonStyle">@style/Widget.DeviceDefault.Button</item>
 
-        <item name="buttonStyleSmall">@android:style/Widget.DeviceDefault.Button.Small</item>
-        <item name="buttonStyleInset">@android:style/Widget.DeviceDefault.Button.Inset</item>
+        <item name="buttonStyleSmall">@style/Widget.DeviceDefault.Button.Small</item>
+        <item name="buttonStyleInset">@style/Widget.DeviceDefault.Button.Inset</item>
 
-        <item name="buttonStyleToggle">@android:style/Widget.DeviceDefault.Button.Toggle</item>
-        <item name="switchStyle">@android:style/Widget.DeviceDefault.CompoundButton.Switch</item>
+        <item name="buttonStyleToggle">@style/Widget.DeviceDefault.Button.Toggle</item>
+        <item name="switchStyle">@style/Widget.DeviceDefault.CompoundButton.Switch</item>
 
-        <item name="borderlessButtonStyle">@android:style/Widget.DeviceDefault.Button.Borderless</item>
+        <item name="borderlessButtonStyle">@style/Widget.DeviceDefault.Button.Borderless</item>
 
-        <item name="listSeparatorTextViewStyle">@android:style/Widget.DeviceDefault.TextView.ListSeparator</item>
+        <item name="listSeparatorTextViewStyle">@style/Widget.DeviceDefault.TextView.ListSeparator</item>
 
         <!-- Window attributes -->
-        <item name="windowTitleStyle">@android:style/WindowTitle.DeviceDefault</item>
-        <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground.DeviceDefault</item>
-        <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Activity</item>
+        <item name="windowTitleStyle">@style/WindowTitle.DeviceDefault</item>
+        <item name="windowTitleBackgroundStyle">@style/WindowTitleBackground.DeviceDefault</item>
+        <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Activity</item>
 
         <!-- Dialog attributes -->
-        <item name="dialogTheme">@android:style/Theme.DeviceDefault.Dialog</item>
+        <item name="dialogTheme">@style/Theme.DeviceDefault.Dialog</item>
 
         <!-- AlertDialog attributes -->
-        <item name="alertDialogTheme">@android:style/Theme.DeviceDefault.Dialog.Alert</item>
-        <item name="alertDialogStyle">@android:style/AlertDialog.DeviceDefault</item>
+        <item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
+        <item name="alertDialogStyle">@style/AlertDialog.DeviceDefault</item>
 
         <!-- Presentation attributes -->
-        <item name="presentationTheme">@android:style/Theme.DeviceDefault.Dialog.Presentation</item>
+        <item name="presentationTheme">@style/Theme.DeviceDefault.Dialog.Presentation</item>
 
         <!-- Text selection handle attributes -->
-        <item name="textSelectHandleWindowStyle">@android:style/Widget.DeviceDefault.TextSelectHandle</item>
-        <item name="textSuggestionsWindowStyle">@android:style/Widget.DeviceDefault.TextSuggestionsPopupWindow</item>
+        <item name="textSelectHandleWindowStyle">@style/Widget.DeviceDefault.TextSelectHandle</item>
+        <item name="textSuggestionsWindowStyle">@style/Widget.DeviceDefault.TextSuggestionsPopupWindow</item>
 
         <!-- Widget styles -->
-        <item name="absListViewStyle">@android:style/Widget.DeviceDefault.AbsListView</item>
-        <item name="autoCompleteTextViewStyle">@android:style/Widget.DeviceDefault.AutoCompleteTextView</item>
-        <item name="checkboxStyle">@android:style/Widget.DeviceDefault.CompoundButton.CheckBox</item>
-        <item name="checkedTextViewStyle">@android:style/Widget.DeviceDefault.CheckedTextView</item>
-        <item name="dropDownListViewStyle">@android:style/Widget.DeviceDefault.ListView.DropDown</item>
-        <item name="editTextStyle">@android:style/Widget.DeviceDefault.EditText</item>
-        <item name="expandableListViewStyle">@android:style/Widget.DeviceDefault.ExpandableListView</item>
-        <item name="expandableListViewWhiteStyle">@android:style/Widget.DeviceDefault.ExpandableListView.White</item>
-        <item name="galleryStyle">@android:style/Widget.DeviceDefault.Gallery</item>
-        <item name="gestureOverlayViewStyle">@android:style/Widget.DeviceDefault.GestureOverlayView</item>
-        <item name="gridViewStyle">@android:style/Widget.DeviceDefault.GridView</item>
-        <item name="imageButtonStyle">@android:style/Widget.DeviceDefault.ImageButton</item>
-        <item name="imageWellStyle">@android:style/Widget.DeviceDefault.ImageWell</item>
-        <item name="listViewStyle">@android:style/Widget.DeviceDefault.ListView</item>
-        <item name="listViewWhiteStyle">@android:style/Widget.DeviceDefault.ListView.White</item>
-        <item name="popupWindowStyle">@android:style/Widget.DeviceDefault.PopupWindow</item>
-        <item name="progressBarStyle">@android:style/Widget.DeviceDefault.ProgressBar</item>
-        <item name="progressBarStyleHorizontal">@android:style/Widget.DeviceDefault.ProgressBar.Horizontal</item>
-        <item name="progressBarStyleSmall">@android:style/Widget.DeviceDefault.ProgressBar.Small</item>
-        <item name="progressBarStyleSmallTitle">@android:style/Widget.DeviceDefault.ProgressBar.Small.Title</item>
-        <item name="progressBarStyleLarge">@android:style/Widget.DeviceDefault.ProgressBar.Large</item>
-        <item name="progressBarStyleInverse">@android:style/Widget.DeviceDefault.ProgressBar.Inverse</item>
-        <item name="progressBarStyleSmallInverse">@android:style/Widget.DeviceDefault.ProgressBar.Small.Inverse</item>
-        <item name="progressBarStyleLargeInverse">@android:style/Widget.DeviceDefault.ProgressBar.Large.Inverse</item>
-        <item name="seekBarStyle">@android:style/Widget.DeviceDefault.SeekBar</item>
-        <item name="ratingBarStyle">@android:style/Widget.DeviceDefault.RatingBar</item>
-        <item name="ratingBarStyleIndicator">@android:style/Widget.DeviceDefault.RatingBar.Indicator</item>
-        <item name="ratingBarStyleSmall">@android:style/Widget.DeviceDefault.RatingBar.Small</item>
-        <item name="radioButtonStyle">@android:style/Widget.DeviceDefault.CompoundButton.RadioButton</item>
-        <item name="scrollViewStyle">@android:style/Widget.DeviceDefault.ScrollView</item>
-        <item name="horizontalScrollViewStyle">@android:style/Widget.DeviceDefault.HorizontalScrollView</item>
-        <item name="dropDownSpinnerStyle">@android:style/Widget.DeviceDefault.Spinner.DropDown</item>
-        <item name="starStyle">@android:style/Widget.DeviceDefault.CompoundButton.Star</item>
-        <item name="tabWidgetStyle">@android:style/Widget.DeviceDefault.TabWidget</item>
-        <item name="textViewStyle">@android:style/Widget.DeviceDefault.TextView</item>
-        <item name="webTextViewStyle">@android:style/Widget.DeviceDefault.WebTextView</item>
-        <item name="webViewStyle">@android:style/Widget.DeviceDefault.WebView</item>
-        <item name="dropDownItemStyle">@android:style/Widget.DeviceDefault.DropDownItem</item>
-        <item name="spinnerDropDownItemStyle">@android:style/Widget.DeviceDefault.DropDownItem.Spinner</item>
-        <item name="spinnerItemStyle">@android:style/Widget.DeviceDefault.TextView.SpinnerItem</item>
-        <item name="dropDownHintAppearance">@android:style/TextAppearance.DeviceDefault.Widget.DropDownHint</item>
-        <item name="keyboardViewStyle">@android:style/Widget.DeviceDefault.KeyboardView</item>
-        <item name="quickContactBadgeStyleWindowSmall">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowSmall</item>
-        <item name="quickContactBadgeStyleWindowMedium">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowMedium</item>
-        <item name="quickContactBadgeStyleWindowLarge">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowLarge</item>
-        <item name="quickContactBadgeStyleSmallWindowSmall">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall</item>
-        <item name="quickContactBadgeStyleSmallWindowMedium">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium</item>
-        <item name="quickContactBadgeStyleSmallWindowLarge">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge</item>
-        <item name="listPopupWindowStyle">@android:style/Widget.DeviceDefault.ListPopupWindow</item>
-        <item name="popupMenuStyle">@android:style/Widget.DeviceDefault.PopupMenu</item>
-        <item name="stackViewStyle">@android:style/Widget.DeviceDefault.StackView</item>
+        <item name="absListViewStyle">@style/Widget.DeviceDefault.AbsListView</item>
+        <item name="autoCompleteTextViewStyle">@style/Widget.DeviceDefault.AutoCompleteTextView</item>
+        <item name="checkboxStyle">@style/Widget.DeviceDefault.CompoundButton.CheckBox</item>
+        <item name="checkedTextViewStyle">@style/Widget.DeviceDefault.CheckedTextView</item>
+        <item name="dropDownListViewStyle">@style/Widget.DeviceDefault.ListView.DropDown</item>
+        <item name="editTextStyle">@style/Widget.DeviceDefault.EditText</item>
+        <item name="expandableListViewStyle">@style/Widget.DeviceDefault.ExpandableListView</item>
+        <item name="expandableListViewWhiteStyle">@style/Widget.DeviceDefault.ExpandableListView.White</item>
+        <item name="galleryStyle">@style/Widget.DeviceDefault.Gallery</item>
+        <item name="gestureOverlayViewStyle">@style/Widget.DeviceDefault.GestureOverlayView</item>
+        <item name="gridViewStyle">@style/Widget.DeviceDefault.GridView</item>
+        <item name="imageButtonStyle">@style/Widget.DeviceDefault.ImageButton</item>
+        <item name="imageWellStyle">@style/Widget.DeviceDefault.ImageWell</item>
+        <item name="listViewStyle">@style/Widget.DeviceDefault.ListView</item>
+        <item name="listViewWhiteStyle">@style/Widget.DeviceDefault.ListView.White</item>
+        <item name="popupWindowStyle">@style/Widget.DeviceDefault.PopupWindow</item>
+        <item name="progressBarStyle">@style/Widget.DeviceDefault.ProgressBar</item>
+        <item name="progressBarStyleHorizontal">@style/Widget.DeviceDefault.ProgressBar.Horizontal</item>
+        <item name="progressBarStyleSmall">@style/Widget.DeviceDefault.ProgressBar.Small</item>
+        <item name="progressBarStyleSmallTitle">@style/Widget.DeviceDefault.ProgressBar.Small.Title</item>
+        <item name="progressBarStyleLarge">@style/Widget.DeviceDefault.ProgressBar.Large</item>
+        <item name="progressBarStyleInverse">@style/Widget.DeviceDefault.ProgressBar.Inverse</item>
+        <item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.ProgressBar.Small.Inverse</item>
+        <item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.ProgressBar.Large.Inverse</item>
+        <item name="seekBarStyle">@style/Widget.DeviceDefault.SeekBar</item>
+        <item name="ratingBarStyle">@style/Widget.DeviceDefault.RatingBar</item>
+        <item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.RatingBar.Indicator</item>
+        <item name="ratingBarStyleSmall">@style/Widget.DeviceDefault.RatingBar.Small</item>
+        <item name="radioButtonStyle">@style/Widget.DeviceDefault.CompoundButton.RadioButton</item>
+        <item name="scrollViewStyle">@style/Widget.DeviceDefault.ScrollView</item>
+        <item name="horizontalScrollViewStyle">@style/Widget.DeviceDefault.HorizontalScrollView</item>
+        <item name="dropDownSpinnerStyle">@style/Widget.DeviceDefault.Spinner.DropDown</item>
+        <item name="starStyle">@style/Widget.DeviceDefault.CompoundButton.Star</item>
+        <item name="tabWidgetStyle">@style/Widget.DeviceDefault.TabWidget</item>
+        <item name="textViewStyle">@style/Widget.DeviceDefault.TextView</item>
+        <item name="webTextViewStyle">@style/Widget.DeviceDefault.WebTextView</item>
+        <item name="webViewStyle">@style/Widget.DeviceDefault.WebView</item>
+        <item name="dropDownItemStyle">@style/Widget.DeviceDefault.DropDownItem</item>
+        <item name="spinnerDropDownItemStyle">@style/Widget.DeviceDefault.DropDownItem.Spinner</item>
+        <item name="spinnerItemStyle">@style/Widget.DeviceDefault.TextView.SpinnerItem</item>
+        <item name="dropDownHintAppearance">@style/TextAppearance.DeviceDefault.Widget.DropDownHint</item>
+        <item name="keyboardViewStyle">@style/Widget.DeviceDefault.KeyboardView</item>
+        <item name="quickContactBadgeStyleWindowSmall">@style/Widget.DeviceDefault.QuickContactBadge.WindowSmall</item>
+        <item name="quickContactBadgeStyleWindowMedium">@style/Widget.DeviceDefault.QuickContactBadge.WindowMedium</item>
+        <item name="quickContactBadgeStyleWindowLarge">@style/Widget.DeviceDefault.QuickContactBadge.WindowLarge</item>
+        <item name="quickContactBadgeStyleSmallWindowSmall">@style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall</item>
+        <item name="quickContactBadgeStyleSmallWindowMedium">@style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium</item>
+        <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge</item>
+        <item name="listPopupWindowStyle">@style/Widget.DeviceDefault.ListPopupWindow</item>
+        <item name="popupMenuStyle">@style/Widget.DeviceDefault.PopupMenu</item>
+        <item name="stackViewStyle">@style/Widget.DeviceDefault.StackView</item>
 
         <!-- Preference styles -->
-        <item name="preferenceScreenStyle">@android:style/Preference.DeviceDefault.PreferenceScreen</item>
-        <item name="preferenceCategoryStyle">@android:style/Preference.DeviceDefault.Category</item>
-        <item name="preferenceStyle">@android:style/Preference.DeviceDefault</item>
-        <item name="preferenceInformationStyle">@android:style/Preference.DeviceDefault.Information</item>
-        <item name="checkBoxPreferenceStyle">@android:style/Preference.DeviceDefault.CheckBoxPreference</item>
-        <item name="switchPreferenceStyle">@android:style/Preference.DeviceDefault.SwitchPreference</item>
-        <item name="yesNoPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference.YesNoPreference</item>
-        <item name="dialogPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference</item>
-        <item name="editTextPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference.EditTextPreference</item>
-        <item name="ringtonePreferenceStyle">@android:style/Preference.DeviceDefault.RingtonePreference</item>
+        <item name="preferenceScreenStyle">@style/Preference.DeviceDefault.PreferenceScreen</item>
+        <item name="preferenceCategoryStyle">@style/Preference.DeviceDefault.Category</item>
+        <item name="preferenceStyle">@style/Preference.DeviceDefault</item>
+        <item name="preferenceInformationStyle">@style/Preference.DeviceDefault.Information</item>
+        <item name="checkBoxPreferenceStyle">@style/Preference.DeviceDefault.CheckBoxPreference</item>
+        <item name="switchPreferenceStyle">@style/Preference.DeviceDefault.SwitchPreference</item>
+        <item name="yesNoPreferenceStyle">@style/Preference.DeviceDefault.DialogPreference.YesNoPreference</item>
+        <item name="dialogPreferenceStyle">@style/Preference.DeviceDefault.DialogPreference</item>
+        <item name="editTextPreferenceStyle">@style/Preference.DeviceDefault.DialogPreference.EditTextPreference</item>
+        <item name="ringtonePreferenceStyle">@style/Preference.DeviceDefault.RingtonePreference</item>
 
         <!-- Action bar styles -->
-        <item name="actionDropDownStyle">@android:style/Widget.DeviceDefault.Spinner.DropDown.ActionBar</item>
-        <item name="actionButtonStyle">@android:style/Widget.DeviceDefault.ActionButton</item>
-        <item name="actionOverflowButtonStyle">@android:style/Widget.DeviceDefault.ActionButton.Overflow</item>
+        <item name="actionDropDownStyle">@style/Widget.DeviceDefault.Spinner.DropDown.ActionBar</item>
+        <item name="actionButtonStyle">@style/Widget.DeviceDefault.ActionButton</item>
+        <item name="actionOverflowButtonStyle">@style/Widget.DeviceDefault.ActionButton.Overflow</item>
         <item name="actionBarTabStyle">@style/Widget.DeviceDefault.ActionBar.TabView</item>
         <item name="actionBarTabBarStyle">@style/Widget.DeviceDefault.ActionBar.TabBar</item>
         <item name="actionBarTabTextStyle">@style/Widget.DeviceDefault.ActionBar.TabText</item>
         <item name="actionModeStyle">@style/Widget.DeviceDefault.ActionMode</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.DeviceDefault.ActionButton.CloseMode</item>
-        <item name="actionBarStyle">@android:style/Widget.DeviceDefault.ActionBar</item>
-        <item name="actionModePopupWindowStyle">@android:style/Widget.DeviceDefault.PopupWindow.ActionMode</item>
+        <item name="actionBarStyle">@style/Widget.DeviceDefault.ActionBar</item>
+        <item name="actionModePopupWindowStyle">@style/Widget.DeviceDefault.PopupWindow.ActionMode</item>
 
-        <item name="buttonBarStyle">@android:style/DeviceDefault.ButtonBar</item>
-        <item name="segmentedButtonStyle">@android:style/DeviceDefault.SegmentedButton</item>
+        <item name="buttonBarStyle">@style/DeviceDefault.ButtonBar</item>
+        <item name="segmentedButtonStyle">@style/DeviceDefault.SegmentedButton</item>
 
         <item name="searchDialogTheme">@style/Theme.DeviceDefault.SearchBar</item>
 
         <!-- PreferenceFrameLayout attributes -->
-        <item name="preferenceFrameLayoutStyle">@android:style/Widget.DeviceDefault.PreferenceFrameLayout</item>
+        <item name="preferenceFrameLayoutStyle">@style/Widget.DeviceDefault.PreferenceFrameLayout</item>
 
         <!-- NumberPicker style-->
         <item name="numberPickerStyle">@style/Widget.DeviceDefault.NumberPicker</item>
@@ -201,165 +201,245 @@
         <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.DeviceDefault.TimePicker.AmPmLabel</item>
 
         <!-- TimePicker dialog theme -->
-        <item name="timePickerDialogTheme">@android:style/Theme.DeviceDefault.Dialog.TimePicker</item>
+        <item name="timePickerDialogTheme">@style/Theme.DeviceDefault.Dialog.TimePicker</item>
 
         <!-- DatePicker style -->
         <item name="datePickerStyle">@style/Widget.DeviceDefault.DatePicker</item>
 
-        <item name="mediaRouteButtonStyle">@android:style/Widget.DeviceDefault.MediaRouteButton</item>
+        <item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.MediaRouteButton</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar -->
-    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Quantum.NoActionBar" >
-    </style>
+    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Quantum.NoActionBar"  />
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar.  This theme
          sets {@link android.R.attr#windowFullscreen} to true.  -->
-    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Quantum.NoActionBar.Fullscreen" >
-    </style>
+    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Quantum.NoActionBar.Fullscreen"  />
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar and
     extending in to overscan region.  This theme
     sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
     to true. -->
-    <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Quantum.NoActionBar.Overscan" >
-    </style>
+    <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Quantum.NoActionBar.Overscan"  />
 
     <!-- Variant of {@link #Theme_DeviceDefault} that has no title bar and translucent
          system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
          {@link android.R.attr#windowTranslucentNavigation} to true. -->
-    <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Quantum.NoActionBar.TranslucentDecor" >
+    <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Quantum.NoActionBar.TranslucentDecor"  />
+
+    <!-- DeviceDefault theme for dialog windows and activities. This changes the window to be
+    floating (not fill the entire screen), and puts a frame around its contents. You can set this
+    theme on an activity if you would like to make an activity that looks like a Dialog. -->
+    <style name="Theme.DeviceDefault.Dialog" parent="Theme.Quantum.Dialog" >
+        <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
+        <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
+        <item name="buttonBarStyle">@style/DeviceDefault.ButtonBar.AlertDialog</item>
+        <item name="borderlessButtonStyle">@style/Widget.DeviceDefault.Button.Borderless.Small</item>
+
+        <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>
+        <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>
     </style>
 
+    <!-- Variant of {@link #Theme_DeviceDefault_Dialog} that has a nice minimum width for a
+    regular dialog. -->
+    <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Quantum.Dialog.MinWidth" />
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Quantum.Dialog.NoActionBar" />
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Dialog_NoActionBar} that has a nice minimum width
+    for a regular dialog. -->
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Quantum.Dialog.NoActionBar.MinWidth" />
+
+    <!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
+    <style name="Theme.DeviceDefault.Dialog.FixedSize">
+        <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
+        <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
+        <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
+        <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+    </style>
+
+    <!-- Variant of Theme.DeviceDefault.Dialog.NoActionBar that has a fixed size. -->
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar.FixedSize">
+        <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
+        <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
+        <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
+        <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+    </style>
+
+    <!-- DeviceDefault theme for a window that will be displayed either full-screen on smaller
+    screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
+    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Quantum.DialogWhenLarge"  />
+
+    <!-- DeviceDefault theme for a window without an action bar that will be displayed either
+    full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
+    xlarge). -->
+    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Quantum.DialogWhenLarge.NoActionBar"  />
+
+    <!-- DeviceDefault theme for a presentation window on a secondary display. -->
+    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Quantum.Dialog.Presentation" />
+
+    <style name="Theme.DeviceDefault.Dialog.TimePicker" parent="Theme.Quantum.Dialog.TimePicker"/>
+
+    <!-- DeviceDefault theme for panel windows. This removes all extraneous window
+    decorations, so you basically have an empty rectangle in which to place your content. It makes
+    the window floating, with a transparent background, and turns off dimming behind the window. -->
+    <style name="Theme.DeviceDefault.Panel" parent="Theme.Quantum.Panel"  />
+
+    <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
+    behind them. -->
+    <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Quantum.Wallpaper"  />
+
+    <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
+    behind them and without an action bar. -->
+    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Quantum.Wallpaper.NoTitleBar"  />
+
+    <!-- DeviceDefault style for input methods, which is used by the
+         {@link android.inputmethodservice.InputMethodService} class.-->
+    <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Quantum.InputMethod"  />
+
+    <!-- DeviceDefault style for input methods, which is used by the
+         {@link android.service.voice.VoiceInteractionSession} class.-->
+    <style name="Theme.DeviceDefault.VoiceInteractionSession" parent="Theme.Quantum.VoiceInteractionSession" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Quantum.Dialog.Alert">
+        <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
+    </style>
+
+    <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Quantum.SearchBar" />
+    <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Quantum.Dialog.NoFrame" />
+
     <!-- Variant of {@link #Theme_DeviceDefault} with a light-colored style -->
     <style name="Theme.DeviceDefault.Light" parent="Theme.Quantum.Light" >
         <!-- Text styles -->
-        <item name="textAppearance">@android:style/TextAppearance.DeviceDefault.Light</item>
-        <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Light.Inverse</item>
+        <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>
+        <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>
 
-        <item name="textAppearanceLarge">@android:style/TextAppearance.DeviceDefault.Light.Large</item>
-        <item name="textAppearanceMedium">@android:style/TextAppearance.DeviceDefault.Light.Medium</item>
-        <item name="textAppearanceSmall">@android:style/TextAppearance.DeviceDefault.Light.Small</item>
-        <item name="textAppearanceLargeInverse">@android:style/TextAppearance.DeviceDefault.Light.Large.Inverse</item>
-        <item name="textAppearanceMediumInverse">@android:style/TextAppearance.DeviceDefault.Light.Medium.Inverse</item>
-        <item name="textAppearanceSmallInverse">@android:style/TextAppearance.DeviceDefault.Light.Small.Inverse</item>
-        <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.DeviceDefault.Light.SearchResult.Title</item>
-        <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.DeviceDefault.Light.SearchResult.Subtitle</item>
+        <item name="textAppearanceLarge">@style/TextAppearance.DeviceDefault.Large</item>
+        <item name="textAppearanceMedium">@style/TextAppearance.DeviceDefault.Medium</item>
+        <item name="textAppearanceSmall">@style/TextAppearance.DeviceDefault.Small</item>
+        <item name="textAppearanceLargeInverse">@style/TextAppearance.DeviceDefault.Large.Inverse</item>
+        <item name="textAppearanceMediumInverse">@style/TextAppearance.DeviceDefault.Medium.Inverse</item>
+        <item name="textAppearanceSmallInverse">@style/TextAppearance.DeviceDefault.Small.Inverse</item>
+        <item name="textAppearanceSearchResultTitle">@style/TextAppearance.DeviceDefault.SearchResult.Title</item>
+        <item name="textAppearanceSearchResultSubtitle">@style/TextAppearance.DeviceDefault.SearchResult.Subtitle</item>
 
-        <item name="textAppearanceButton">@android:style/TextAppearance.DeviceDefault.Light.Widget.Button</item>
+        <item name="textAppearanceButton">@style/TextAppearance.DeviceDefault.Widget.Button</item>
 
-        <item name="textAppearanceLargePopupMenu">@android:style/TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Large</item>
-        <item name="textAppearanceSmallPopupMenu">@android:style/TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Small</item>
+        <item name="textAppearanceLargePopupMenu">@style/TextAppearance.DeviceDefault.Widget.PopupMenu.Large</item>
+        <item name="textAppearanceSmallPopupMenu">@style/TextAppearance.DeviceDefault.Widget.PopupMenu.Small</item>
 
         <!-- Button styles -->
-        <item name="buttonStyle">@android:style/Widget.DeviceDefault.Light.Button</item>
+        <item name="buttonStyle">@style/Widget.DeviceDefault.Light.Button</item>
 
-        <item name="buttonStyleSmall">@android:style/Widget.DeviceDefault.Light.Button.Small</item>
-        <item name="buttonStyleInset">@android:style/Widget.DeviceDefault.Light.Button.Inset</item>
+        <item name="buttonStyleSmall">@style/Widget.DeviceDefault.Light.Button.Small</item>
+        <item name="buttonStyleInset">@style/Widget.DeviceDefault.Light.Button.Inset</item>
 
-        <item name="buttonStyleToggle">@android:style/Widget.DeviceDefault.Light.Button.Toggle</item>
+        <item name="buttonStyleToggle">@style/Widget.DeviceDefault.Light.Button.Toggle</item>
 
-        <item name="borderlessButtonStyle">@android:style/Widget.DeviceDefault.Light.Button.Borderless</item>
+        <item name="borderlessButtonStyle">@style/Widget.DeviceDefault.Light.Button.Borderless</item>
 
-        <item name="listSeparatorTextViewStyle">@android:style/Widget.DeviceDefault.Light.TextView.ListSeparator</item>
+        <item name="listSeparatorTextViewStyle">@style/Widget.DeviceDefault.Light.TextView.ListSeparator</item>
 
-        <item name="windowTitleStyle">@android:style/WindowTitle.DeviceDefault</item>
-        <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground.DeviceDefault</item>
-        <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Activity</item>
+        <item name="windowTitleStyle">@style/WindowTitle.DeviceDefault</item>
+        <item name="windowTitleBackgroundStyle">@style/WindowTitleBackground.DeviceDefault</item>
+        <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Activity</item>
 
         <!-- Dialog attributes -->
-        <item name="dialogTheme">@android:style/Theme.DeviceDefault.Light.Dialog</item>
+        <item name="dialogTheme">@style/Theme.DeviceDefault.Light.Dialog</item>
 
         <!-- AlertDialog attributes -->
-        <item name="alertDialogTheme">@android:style/Theme.DeviceDefault.Light.Dialog.Alert</item>
-        <item name="alertDialogStyle">@android:style/AlertDialog.DeviceDefault.Light</item>
+        <item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
+        <item name="alertDialogStyle">@style/AlertDialog.DeviceDefault.Light</item>
 
         <!-- Presentation attributes -->
-        <item name="presentationTheme">@android:style/Theme.DeviceDefault.Light.Dialog.Presentation</item>
+        <item name="presentationTheme">@style/Theme.DeviceDefault.Light.Dialog.Presentation</item>
 
         <!-- Text selection handle attributes -->
-        <item name="textSelectHandleWindowStyle">@android:style/Widget.DeviceDefault.TextSelectHandle</item>
-        <item name="textSuggestionsWindowStyle">@android:style/Widget.DeviceDefault.Light.TextSuggestionsPopupWindow</item>
+        <item name="textSelectHandleWindowStyle">@style/Widget.DeviceDefault.TextSelectHandle</item>
+        <item name="textSuggestionsWindowStyle">@style/Widget.DeviceDefault.Light.TextSuggestionsPopupWindow</item>
 
         <!-- Widget styles -->
-        <item name="absListViewStyle">@android:style/Widget.DeviceDefault.Light.AbsListView</item>
-        <item name="autoCompleteTextViewStyle">@android:style/Widget.DeviceDefault.Light.AutoCompleteTextView</item>
-        <item name="checkboxStyle">@android:style/Widget.DeviceDefault.Light.CompoundButton.CheckBox</item>
-        <item name="checkedTextViewStyle">@android:style/Widget.DeviceDefault.Light.CheckedTextView</item>
-        <item name="dropDownListViewStyle">@android:style/Widget.DeviceDefault.Light.ListView.DropDown</item>
-        <item name="editTextStyle">@android:style/Widget.DeviceDefault.Light.EditText</item>
-        <item name="expandableListViewStyle">@android:style/Widget.DeviceDefault.Light.ExpandableListView</item>
-        <item name="expandableListViewWhiteStyle">@android:style/Widget.DeviceDefault.Light.ExpandableListView.White</item>
-        <item name="galleryStyle">@android:style/Widget.DeviceDefault.Light.Gallery</item>
-        <item name="gestureOverlayViewStyle">@android:style/Widget.DeviceDefault.Light.GestureOverlayView</item>
-        <item name="gridViewStyle">@android:style/Widget.DeviceDefault.Light.GridView</item>
-        <item name="imageButtonStyle">@android:style/Widget.DeviceDefault.Light.ImageButton</item>
-        <item name="imageWellStyle">@android:style/Widget.DeviceDefault.Light.ImageWell</item>
-        <item name="listViewStyle">@android:style/Widget.DeviceDefault.Light.ListView</item>
-        <item name="listViewWhiteStyle">@android:style/Widget.DeviceDefault.Light.ListView.White</item>
-        <item name="popupWindowStyle">@android:style/Widget.DeviceDefault.Light.PopupWindow</item>
-        <item name="progressBarStyle">@android:style/Widget.DeviceDefault.Light.ProgressBar</item>
-        <item name="progressBarStyleHorizontal">@android:style/Widget.DeviceDefault.Light.ProgressBar.Horizontal</item>
-        <item name="progressBarStyleSmall">@android:style/Widget.DeviceDefault.Light.ProgressBar.Small</item>
-        <item name="progressBarStyleSmallTitle">@android:style/Widget.DeviceDefault.Light.ProgressBar.Small.Title</item>
-        <item name="progressBarStyleLarge">@android:style/Widget.DeviceDefault.Light.ProgressBar.Large</item>
-        <item name="progressBarStyleInverse">@android:style/Widget.DeviceDefault.Light.ProgressBar.Inverse</item>
-        <item name="progressBarStyleSmallInverse">@android:style/Widget.DeviceDefault.Light.ProgressBar.Small.Inverse</item>
-        <item name="progressBarStyleLargeInverse">@android:style/Widget.DeviceDefault.Light.ProgressBar.Large.Inverse</item>
-        <item name="seekBarStyle">@android:style/Widget.DeviceDefault.Light.SeekBar</item>
-        <item name="ratingBarStyle">@android:style/Widget.DeviceDefault.Light.RatingBar</item>
-        <item name="ratingBarStyleIndicator">@android:style/Widget.DeviceDefault.Light.RatingBar.Indicator</item>
-        <item name="ratingBarStyleSmall">@android:style/Widget.DeviceDefault.Light.RatingBar.Small</item>
-        <item name="radioButtonStyle">@android:style/Widget.DeviceDefault.Light.CompoundButton.RadioButton</item>
-        <item name="scrollViewStyle">@android:style/Widget.DeviceDefault.Light.ScrollView</item>
-        <item name="horizontalScrollViewStyle">@android:style/Widget.DeviceDefault.Light.HorizontalScrollView</item>
-        <item name="dropDownSpinnerStyle">@android:style/Widget.DeviceDefault.Light.Spinner.DropDown</item>
-        <item name="starStyle">@android:style/Widget.DeviceDefault.Light.CompoundButton.Star</item>
-        <item name="tabWidgetStyle">@android:style/Widget.DeviceDefault.Light.TabWidget</item>
-        <item name="textViewStyle">@android:style/Widget.DeviceDefault.Light.TextView</item>
-        <item name="webTextViewStyle">@android:style/Widget.DeviceDefault.Light.WebTextView</item>
-        <item name="webViewStyle">@android:style/Widget.DeviceDefault.Light.WebView</item>
-        <item name="dropDownItemStyle">@android:style/Widget.DeviceDefault.Light.DropDownItem</item>
-        <item name="spinnerDropDownItemStyle">@android:style/Widget.DeviceDefault.Light.DropDownItem.Spinner</item>
-        <item name="spinnerItemStyle">@android:style/Widget.DeviceDefault.Light.TextView.SpinnerItem</item>
-        <item name="dropDownHintAppearance">@android:style/TextAppearance.DeviceDefault.Widget.DropDownHint</item>
-        <item name="keyboardViewStyle">@android:style/Widget.DeviceDefault.KeyboardView</item>
-        <item name="quickContactBadgeStyleWindowSmall">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowSmall</item>
-        <item name="quickContactBadgeStyleWindowMedium">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowMedium</item>
-        <item name="quickContactBadgeStyleWindowLarge">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowLarge</item>
-        <item name="quickContactBadgeStyleSmallWindowSmall">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall</item>
-        <item name="quickContactBadgeStyleSmallWindowMedium">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium</item>
-        <item name="quickContactBadgeStyleSmallWindowLarge">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge</item>
-        <item name="listPopupWindowStyle">@android:style/Widget.DeviceDefault.Light.ListPopupWindow</item>
-        <item name="popupMenuStyle">@android:style/Widget.DeviceDefault.Light.PopupMenu</item>
-        <item name="stackViewStyle">@android:style/Widget.DeviceDefault.StackView</item>
+        <item name="absListViewStyle">@style/Widget.DeviceDefault.Light.AbsListView</item>
+        <item name="autoCompleteTextViewStyle">@style/Widget.DeviceDefault.Light.AutoCompleteTextView</item>
+        <item name="checkboxStyle">@style/Widget.DeviceDefault.Light.CompoundButton.CheckBox</item>
+        <item name="checkedTextViewStyle">@style/Widget.DeviceDefault.Light.CheckedTextView</item>
+        <item name="dropDownListViewStyle">@style/Widget.DeviceDefault.Light.ListView.DropDown</item>
+        <item name="editTextStyle">@style/Widget.DeviceDefault.Light.EditText</item>
+        <item name="expandableListViewStyle">@style/Widget.DeviceDefault.Light.ExpandableListView</item>
+        <item name="expandableListViewWhiteStyle">@style/Widget.DeviceDefault.Light.ExpandableListView.White</item>
+        <item name="galleryStyle">@style/Widget.DeviceDefault.Light.Gallery</item>
+        <item name="gestureOverlayViewStyle">@style/Widget.DeviceDefault.Light.GestureOverlayView</item>
+        <item name="gridViewStyle">@style/Widget.DeviceDefault.Light.GridView</item>
+        <item name="imageButtonStyle">@style/Widget.DeviceDefault.Light.ImageButton</item>
+        <item name="imageWellStyle">@style/Widget.DeviceDefault.Light.ImageWell</item>
+        <item name="listViewStyle">@style/Widget.DeviceDefault.Light.ListView</item>
+        <item name="listViewWhiteStyle">@style/Widget.DeviceDefault.Light.ListView.White</item>
+        <item name="popupWindowStyle">@style/Widget.DeviceDefault.Light.PopupWindow</item>
+        <item name="progressBarStyle">@style/Widget.DeviceDefault.Light.ProgressBar</item>
+        <item name="progressBarStyleHorizontal">@style/Widget.DeviceDefault.Light.ProgressBar.Horizontal</item>
+        <item name="progressBarStyleSmall">@style/Widget.DeviceDefault.Light.ProgressBar.Small</item>
+        <item name="progressBarStyleSmallTitle">@style/Widget.DeviceDefault.Light.ProgressBar.Small.Title</item>
+        <item name="progressBarStyleLarge">@style/Widget.DeviceDefault.Light.ProgressBar.Large</item>
+        <item name="progressBarStyleInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Inverse</item>
+        <item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Small.Inverse</item>
+        <item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Large.Inverse</item>
+        <item name="seekBarStyle">@style/Widget.DeviceDefault.Light.SeekBar</item>
+        <item name="ratingBarStyle">@style/Widget.DeviceDefault.Light.RatingBar</item>
+        <item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.Light.RatingBar.Indicator</item>
+        <item name="ratingBarStyleSmall">@style/Widget.DeviceDefault.Light.RatingBar.Small</item>
+        <item name="radioButtonStyle">@style/Widget.DeviceDefault.Light.CompoundButton.RadioButton</item>
+        <item name="scrollViewStyle">@style/Widget.DeviceDefault.Light.ScrollView</item>
+        <item name="horizontalScrollViewStyle">@style/Widget.DeviceDefault.Light.HorizontalScrollView</item>
+        <item name="dropDownSpinnerStyle">@style/Widget.DeviceDefault.Light.Spinner.DropDown</item>
+        <item name="starStyle">@style/Widget.DeviceDefault.Light.CompoundButton.Star</item>
+        <item name="tabWidgetStyle">@style/Widget.DeviceDefault.Light.TabWidget</item>
+        <item name="textViewStyle">@style/Widget.DeviceDefault.Light.TextView</item>
+        <item name="webTextViewStyle">@style/Widget.DeviceDefault.Light.WebTextView</item>
+        <item name="webViewStyle">@style/Widget.DeviceDefault.Light.WebView</item>
+        <item name="dropDownItemStyle">@style/Widget.DeviceDefault.Light.DropDownItem</item>
+        <item name="spinnerDropDownItemStyle">@style/Widget.DeviceDefault.Light.DropDownItem.Spinner</item>
+        <item name="spinnerItemStyle">@style/Widget.DeviceDefault.Light.TextView.SpinnerItem</item>
+        <item name="dropDownHintAppearance">@style/TextAppearance.DeviceDefault.Widget.DropDownHint</item>
+        <item name="keyboardViewStyle">@style/Widget.DeviceDefault.KeyboardView</item>
+        <item name="quickContactBadgeStyleWindowSmall">@style/Widget.DeviceDefault.QuickContactBadge.WindowSmall</item>
+        <item name="quickContactBadgeStyleWindowMedium">@style/Widget.DeviceDefault.QuickContactBadge.WindowMedium</item>
+        <item name="quickContactBadgeStyleWindowLarge">@style/Widget.DeviceDefault.QuickContactBadge.WindowLarge</item>
+        <item name="quickContactBadgeStyleSmallWindowSmall">@style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall</item>
+        <item name="quickContactBadgeStyleSmallWindowMedium">@style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium</item>
+        <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge</item>
+        <item name="listPopupWindowStyle">@style/Widget.DeviceDefault.Light.ListPopupWindow</item>
+        <item name="popupMenuStyle">@style/Widget.DeviceDefault.Light.PopupMenu</item>
+        <item name="stackViewStyle">@style/Widget.DeviceDefault.Light.StackView</item>
 
         <!-- Preference styles -->
-        <item name="preferenceScreenStyle">@android:style/Preference.DeviceDefault.PreferenceScreen</item>
-        <item name="preferenceCategoryStyle">@android:style/Preference.DeviceDefault.Category</item>
-        <item name="preferenceStyle">@android:style/Preference.DeviceDefault</item>
-        <item name="preferenceInformationStyle">@android:style/Preference.DeviceDefault.Information</item>
-        <item name="checkBoxPreferenceStyle">@android:style/Preference.DeviceDefault.CheckBoxPreference</item>
-        <item name="switchPreferenceStyle">@android:style/Preference.DeviceDefault.SwitchPreference</item>
-        <item name="yesNoPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference.YesNoPreference</item>
-        <item name="dialogPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference</item>
-        <item name="editTextPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference.EditTextPreference</item>
-        <item name="ringtonePreferenceStyle">@android:style/Preference.DeviceDefault.RingtonePreference</item>
+        <item name="preferenceScreenStyle">@style/Preference.DeviceDefault.PreferenceScreen</item>
+        <item name="preferenceCategoryStyle">@style/Preference.DeviceDefault.Category</item>
+        <item name="preferenceStyle">@style/Preference.DeviceDefault</item>
+        <item name="preferenceInformationStyle">@style/Preference.DeviceDefault.Information</item>
+        <item name="checkBoxPreferenceStyle">@style/Preference.DeviceDefault.CheckBoxPreference</item>
+        <item name="switchPreferenceStyle">@style/Preference.DeviceDefault.SwitchPreference</item>
+        <item name="yesNoPreferenceStyle">@style/Preference.DeviceDefault.DialogPreference.YesNoPreference</item>
+        <item name="dialogPreferenceStyle">@style/Preference.DeviceDefault.DialogPreference</item>
+        <item name="editTextPreferenceStyle">@style/Preference.DeviceDefault.DialogPreference.EditTextPreference</item>
+        <item name="ringtonePreferenceStyle">@style/Preference.DeviceDefault.RingtonePreference</item>
 
         <!-- Action bar styles -->
-        <item name="actionDropDownStyle">@android:style/Widget.DeviceDefault.Light.Spinner.DropDown.ActionBar</item>
-        <item name="actionButtonStyle">@android:style/Widget.DeviceDefault.Light.ActionButton</item>
-        <item name="actionOverflowButtonStyle">@android:style/Widget.DeviceDefault.Light.ActionButton.Overflow</item>
+        <item name="actionDropDownStyle">@style/Widget.DeviceDefault.Light.Spinner.DropDown.ActionBar</item>
+        <item name="actionButtonStyle">@style/Widget.DeviceDefault.Light.ActionButton</item>
+        <item name="actionOverflowButtonStyle">@style/Widget.DeviceDefault.Light.ActionButton.Overflow</item>
         <item name="actionBarTabStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabView</item>
         <item name="actionBarTabBarStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabBar</item>
         <item name="actionBarTabTextStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabText</item>
         <item name="actionModeStyle">@style/Widget.DeviceDefault.Light.ActionMode</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.DeviceDefault.Light.ActionButton.CloseMode</item>
-        <item name="actionBarStyle">@android:style/Widget.DeviceDefault.Light.ActionBar</item>
-        <item name="actionModePopupWindowStyle">@android:style/Widget.DeviceDefault.Light.PopupWindow.ActionMode</item>
+        <item name="actionBarStyle">@style/Widget.DeviceDefault.Light.ActionBar</item>
+        <item name="actionModePopupWindowStyle">@style/Widget.DeviceDefault.Light.PopupWindow.ActionMode</item>
 
-        <item name="buttonBarStyle">@android:style/DeviceDefault.Light.ButtonBar</item>
-        <item name="segmentedButtonStyle">@android:style/DeviceDefault.Light.SegmentedButton</item>
+        <item name="buttonBarStyle">@style/DeviceDefault.Light.ButtonBar</item>
+        <item name="segmentedButtonStyle">@style/DeviceDefault.Light.SegmentedButton</item>
 
         <item name="searchDialogTheme">@style/Theme.DeviceDefault.Light.SearchBar</item>
 
@@ -373,216 +453,117 @@
         <item name="timePickerStyle">@style/Widget.DeviceDefault.Light.TimePicker</item>
 
         <!-- TimePicker Header time label text appearance -->
-        <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.DeviceDefault.Light.TimePicker.TimeLabel</item>
+        <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.DeviceDefault.TimePicker.TimeLabel</item>
 
         <!-- TimePicker Header am pm label text appearance -->
-        <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.DeviceDefault.Light.TimePicker.AmPmLabel</item>
+        <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.DeviceDefault.TimePicker.AmPmLabel</item>
 
         <!-- TimePicker dialog theme -->
-        <item name="timePickerDialogTheme">@android:style/Theme.DeviceDefault.Light.Dialog.TimePicker</item>
+        <item name="timePickerDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.TimePicker</item>
 
         <!-- DatePicker style -->
         <item name="datePickerStyle">@style/Widget.DeviceDefault.Light.DatePicker</item>
 
-        <item name="mediaRouteButtonStyle">@android:style/Widget.DeviceDefault.Light.MediaRouteButton</item>
-    </style>
-    <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Quantum.Light.NoActionBar" >
-    </style>
-    <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar.
-         This theme sets {@link android.R.attr#windowFullscreen} to true.  -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Quantum.Light.NoActionBar.Fullscreen" >
-    </style>
-    <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar
-    and extending in to overscan region.  This theme
-    sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
-    to true. -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan"
-           parent="Theme.Quantum.Light.NoActionBar.Overscan" >
-    </style>
-    <!-- Variant of {@link #Theme_DeviceDefault_Light} that has no title bar and translucent
-         system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
-         {@link android.R.attr#windowTranslucentNavigation} to true. -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor"
-           parent="Theme.Quantum.Light.NoActionBar.TranslucentDecor" >
-    </style>
-    <!-- DeviceDefault theme for dialog windows and activities. This changes the window to be
-    floating (not fill the entire screen), and puts a frame around its contents. You can set this
-    theme on an activity if you would like to make an activity that looks like a Dialog. -->
-    <style name="Theme.DeviceDefault.Dialog" parent="Theme.Quantum.Dialog" >
-        <item name="android:windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault</item>
-        <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Dialog</item>
-
-        <item name="android:buttonBarStyle">@android:style/DeviceDefault.ButtonBar.AlertDialog</item>
-        <item name="borderlessButtonStyle">@android:style/Widget.DeviceDefault.Button.Borderless.Small</item>
-
-        <item name="textAppearance">@android:style/TextAppearance.DeviceDefault</item>
-        <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Inverse</item>
-    </style>
-    <!-- Variant of {@link #Theme_DeviceDefault_Dialog} that has a nice minimum width for a
-    regular dialog. -->
-    <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Quantum.Dialog.MinWidth" >
-
-    </style>
-    <!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
-    <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Quantum.Dialog.NoActionBar" >
-
-    </style>
-    <!-- Variant of {@link #Theme_DeviceDefault_Dialog_NoActionBar} that has a nice minimum width
-    for a regular dialog. -->
-    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Quantum.Dialog.NoActionBar.MinWidth" >
-
+        <item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.Light.MediaRouteButton</item>
     </style>
 
-    <!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
-    <style name="Theme.DeviceDefault.Dialog.FixedSize">
-        <item name="windowFixedWidthMajor">@android:dimen/dialog_fixed_width_major</item>
-        <item name="windowFixedWidthMinor">@android:dimen/dialog_fixed_width_minor</item>
-        <item name="windowFixedHeightMajor">@android:dimen/dialog_fixed_height_major</item>
-        <item name="windowFixedHeightMinor">@android:dimen/dialog_fixed_height_minor</item>
-    </style>
-
-    <!-- Variant of Theme.DeviceDefault.Dialog.NoActionBar that has a fixed size. -->
-    <style name="Theme.DeviceDefault.Dialog.NoActionBar.FixedSize">
-        <item name="windowFixedWidthMajor">@android:dimen/dialog_fixed_width_major</item>
-        <item name="windowFixedWidthMinor">@android:dimen/dialog_fixed_width_minor</item>
-        <item name="windowFixedHeightMajor">@android:dimen/dialog_fixed_height_major</item>
-        <item name="windowFixedHeightMinor">@android:dimen/dialog_fixed_height_minor</item>
-    </style>
-
-    <!-- DeviceDefault light theme for dialog windows and activities. This changes the window to be
-    floating (not fill the entire screen), and puts a frame around its contents. You can set this
-    theme on an activity if you would like to make an activity that looks like a Dialog.-->
-    <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Quantum.Light.Dialog" >
-        <item name="android:windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault.Light</item>
-        <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Dialog</item>
-
-        <item name="android:buttonBarStyle">@android:style/DeviceDefault.Light.ButtonBar.AlertDialog</item>
-        <item name="borderlessButtonStyle">@android:style/Widget.DeviceDefault.Light.Button.Borderless.Small</item>
-
-        <item name="textAppearance">@android:style/TextAppearance.DeviceDefault.Light</item>
-        <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Light.Inverse</item>
-    </style>
-    <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} that has a nice minimum width for a
-    regular dialog. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Quantum.Light.Dialog.MinWidth" >
-
-    </style>
-     <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} without an action bar -->
-    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Quantum.Light.Dialog.NoActionBar" >
-
-    </style>
-    <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog_NoActionBar} that has a nice minimum
-    width for a regular dialog. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Quantum.Light.Dialog.NoActionBar.MinWidth" >
-
-    </style>
-
-    <!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.FixedSize">
-        <item name="windowFixedWidthMajor">@android:dimen/dialog_fixed_width_major</item>
-        <item name="windowFixedWidthMinor">@android:dimen/dialog_fixed_width_minor</item>
-        <item name="windowFixedHeightMajor">@android:dimen/dialog_fixed_height_major</item>
-        <item name="windowFixedHeightMinor">@android:dimen/dialog_fixed_height_minor</item>
-    </style>
-
-    <!-- Variant of Theme.DeviceDefault.Dialog.NoActionBar that has a fixed size. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.FixedSize">
-        <item name="windowFixedWidthMajor">@android:dimen/dialog_fixed_width_major</item>
-        <item name="windowFixedWidthMinor">@android:dimen/dialog_fixed_width_minor</item>
-        <item name="windowFixedHeightMajor">@android:dimen/dialog_fixed_height_major</item>
-        <item name="windowFixedHeightMinor">@android:dimen/dialog_fixed_height_minor</item>
-    </style>
-
-    <!-- DeviceDefault theme for a window that will be displayed either full-screen on smaller
-    screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
-    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Quantum.DialogWhenLarge" >
-
-    </style>
-    <!-- DeviceDefault theme for a window without an action bar that will be displayed either
-    full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
-    xlarge). -->
-    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Quantum.DialogWhenLarge.NoActionBar" >
-
-    </style>
-    <!-- DeviceDefault light theme for a window that will be displayed either full-screen on smaller
-    screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
-    <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Quantum.Light.DialogWhenLarge" >
-
-    </style>
-    <!-- DeviceDefault light theme for a window without an action bar that will be displayed either
-    full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
-    xlarge). -->
-    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Quantum.Light.DialogWhenLarge.NoActionBar" >
-
-    </style>
-
-    <!-- DeviceDefault theme for a presentation window on a secondary display. -->
-    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Quantum.Dialog.Presentation">
-    </style>
-
-    <!-- DeviceDefault light theme for a presentation window on a secondary display. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Quantum.Light.Dialog.Presentation">
-    </style>
-
-    <!-- DeviceDefault theme for panel windows. This removes all extraneous window
-    decorations, so you basically have an empty rectangle in which to place your content. It makes
-    the window floating, with a transparent background, and turns off dimming behind the window. -->
-    <style name="Theme.DeviceDefault.Panel" parent="Theme.Quantum.Panel" >
-
-    </style>
-    <!-- DeviceDefault light theme for panel windows. This removes all extraneous window
-    decorations, so you basically have an empty rectangle in which to place your content. It makes
-    the window floating, with a transparent background, and turns off dimming behind the window. -->
-    <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Quantum.Light.Panel" >
-
-    </style>
-    <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
-    behind them. -->
-    <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Quantum.Wallpaper" >
-
-    </style>
-    <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
-    behind them and without an action bar. -->
-    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Quantum.Wallpaper.NoTitleBar" >
-
-    </style>
-    <!-- DeviceDefault style for input methods, which is used by the
-         {@link android.inputmethodservice.InputMethodService} class.-->
-    <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Quantum.InputMethod" >
-
-    </style>
     <!-- Variant of the DeviceDefault (light) theme that has a solid (opaque) action bar with an
     inverse color profile. -->
     <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Quantum.Light.DarkActionBar" >
-        <item name="android:actionBarStyle">@android:style/Widget.DeviceDefault.Light.ActionBar.Solid.Inverse</item>
-
-        <item name="actionDropDownStyle">@android:style/Widget.DeviceDefault.Spinner.DropDown.ActionBar</item>
-        <item name="actionButtonStyle">@android:style/Widget.DeviceDefault.ActionButton</item>
-        <item name="actionOverflowButtonStyle">@android:style/Widget.DeviceDefault.ActionButton.Overflow</item>
+        <item name="actionBarStyle">@style/Widget.DeviceDefault.Light.ActionBar.Solid.Inverse</item>
+        <item name="actionDropDownStyle">@style/Widget.DeviceDefault.Spinner.DropDown.ActionBar</item>
+        <item name="actionButtonStyle">@style/Widget.DeviceDefault.ActionButton</item>
+        <item name="actionOverflowButtonStyle">@style/Widget.DeviceDefault.ActionButton.Overflow</item>
         <item name="actionBarTabStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabView.Inverse</item>
         <item name="actionBarTabBarStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabBar.Inverse</item>
         <item name="actionBarTabTextStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabText.Inverse</item>
         <item name="actionModeStyle">@style/Widget.DeviceDefault.Light.ActionMode.Inverse</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.DeviceDefault.ActionButton.CloseMode</item>
-        <item name="actionModePopupWindowStyle">@android:style/Widget.DeviceDefault.PopupWindow.ActionMode</item>
-
+        <item name="actionModePopupWindowStyle">@style/Widget.DeviceDefault.PopupWindow.ActionMode</item>
     </style>
 
-    <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Quantum.Dialog.Alert">
-        <item name="windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault</item>
+    <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar -->
+    <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Quantum.Light.NoActionBar"  />
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar.
+         This theme sets {@link android.R.attr#windowFullscreen} to true.  -->
+    <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Quantum.Light.NoActionBar.Fullscreen"  />
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar
+    and extending in to overscan region.  This theme
+    sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
+    to true. -->
+    <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan" parent="Theme.Quantum.Light.NoActionBar.Overscan" />
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Light} that has no title bar and translucent
+         system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
+         {@link android.R.attr#windowTranslucentNavigation} to true. -->
+    <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor" parent="Theme.Quantum.Light.NoActionBar.TranslucentDecor" />
+
+    <!-- DeviceDefault light theme for dialog windows and activities. This changes the window to be
+    floating (not fill the entire screen), and puts a frame around its contents. You can set this
+    theme on an activity if you would like to make an activity that looks like a Dialog.-->
+    <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Quantum.Light.Dialog" >
+        <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
+        <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
+        <item name="buttonBarStyle">@style/DeviceDefault.Light.ButtonBar.AlertDialog</item>
+        <item name="borderlessButtonStyle">@style/Widget.DeviceDefault.Light.Button.Borderless.Small</item>
+
+        <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>
+        <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>
     </style>
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} that has a nice minimum width for a
+    regular dialog. -->
+    <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Quantum.Light.Dialog.MinWidth" />
+
+     <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} without an action bar -->
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Quantum.Light.Dialog.NoActionBar" />
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog_NoActionBar} that has a nice minimum
+    width for a regular dialog. -->
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Quantum.Light.Dialog.NoActionBar.MinWidth" />
+
+    <!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
+    <style name="Theme.DeviceDefault.Light.Dialog.FixedSize">
+        <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
+        <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
+        <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
+        <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+    </style>
+
+    <!-- Variant of Theme.DeviceDefault.Dialog.NoActionBar that has a fixed size. -->
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.FixedSize">
+        <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
+        <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
+        <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
+        <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+    </style>
+
+    <!-- DeviceDefault light theme for a window that will be displayed either full-screen on smaller
+    screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Quantum.Light.DialogWhenLarge"  />
+
+    <!-- DeviceDefault light theme for a window without an action bar that will be displayed either
+    full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
+    xlarge). -->
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Quantum.Light.DialogWhenLarge.NoActionBar"  />
+
+    <!-- DeviceDefault light theme for a presentation window on a secondary display. -->
+    <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Quantum.Light.Dialog.Presentation" />
+
+    <style name="Theme.DeviceDefault.Light.Dialog.TimePicker" parent="Theme.Quantum.Light.Dialog.TimePicker"/>
+
+    <!-- DeviceDefault light theme for panel windows. This removes all extraneous window
+    decorations, so you basically have an empty rectangle in which to place your content. It makes
+    the window floating, with a transparent background, and turns off dimming behind the window. -->
+    <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Quantum.Light.Panel"  />
+
     <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Quantum.Light.Dialog.Alert">
-        <item name="windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault.Light</item>
-    </style>
-    <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Quantum.SearchBar">
-
-    </style>
-    <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Quantum.Light.SearchBar">
-
+        <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
     </style>
 
-    <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Quantum.Dialog.NoFrame">
-    </style>
+    <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Quantum.Light.SearchBar" />
 
 </resources>
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index f51b8df..39df700 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -15,20 +15,51 @@
 -->
 <resources>
     <style name="Theme.Micro" parent="Theme.Holo.NoActionBar">
-        <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
-        <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
-        <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+        <item name="alertDialogTheme">@style/Theme.Micro.Dialog.Alert</item>
+        <item name="alertDialogStyle">@style/AlertDialog.Micro</item>
+        <item name="dialogTheme">@style/Theme.Micro.Dialog</item>
+        <item name="textViewStyle">@style/Widget.Micro.TextView</item>
+
+        <item name="numberPickerStyle">@style/Widget.Micro.NumberPicker</item>
+        <item name="windowAnimationStyle">@style/Animation.SwipeDismiss</item>
         <item name="windowIsFloating">false</item>
         <item name="windowIsTranslucent">true</item>
         <item name="windowSwipeToDismiss">true</item>
 	</style>
 
     <style name="Theme.Micro.Light" parent="Theme.Holo.Light.NoActionBar">
-        <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
-        <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
-        <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+        <item name="alertDialogTheme">@style/Theme.Micro.Dialog.Alert</item>
+        <item name="alertDialogStyle">@style/AlertDialog.Micro</item>
+        <item name="dialogTheme">@style/Theme.Micro.Dialog</item>
+        <item name="textViewStyle">@style/Widget.Micro.TextView</item>
+        <item name="numberPickerStyle">@style/Widget.Micro.NumberPicker</item>
+        <item name="windowAnimationStyle">@style/Animation.SwipeDismiss</item>
         <item name="windowIsFloating">false</item>
         <item name="windowIsTranslucent">true</item>
         <item name="windowSwipeToDismiss">true</item>
     </style>
+
+    <style name="Theme.Micro.Dialog" parent="Theme.Holo.Light.Dialog">
+        <item name="windowTitleStyle">@android:style/DialogWindowTitle.Micro</item>
+        <item name="windowIsFloating">false</item>
+        <item name="windowFullscreen">true</item>
+        <item name="textAppearance">@style/TextAppearance.Micro</item>
+        <item name="textAppearanceInverse">@style/TextAppearance.Micro</item>
+    </style>
+
+    <style name="Theme.Micro.Dialog.Alert" parent="Theme.Holo.Light.Dialog.Alert">
+        <item name="windowTitleStyle">@style/DialogWindowTitle.Micro</item>
+        <item name="alertDialogStyle">@style/AlertDialog.Micro</item>
+        <item name="windowIsFloating">false</item>
+    </style>
+
+    <style name="Theme.Micro.Dialog.AppError" parent="Theme.Micro.Dialog">
+        <item name="windowBackground">@null</item>
+        <item name="alertDialogStyle">@style/AlertDialog.Micro</item>
+        <item name="windowOverscan">true</item>
+        <item name="windowCloseOnTouchOutside">false</item>
+        <item name="textSize">20sp</item>
+        <item name="fontFamily">sans-serif-condensed-light</item>
+        <item name="textColor">@color/micro_text_light</item>
+    </style>
 </resources>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index 9f76eae..6115fa7 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -391,8 +391,8 @@
         <item name="backgroundDimAmount">0.6</item>
 
         <!-- Text styles -->
-        <item name="textAppearance">@style/TextAppearance.Quantum.Light</item>
-        <item name="textAppearanceInverse">@style/TextAppearance.Quantum.Light.Inverse</item>
+        <item name="textAppearance">@style/TextAppearance.Quantum</item>
+        <item name="textAppearanceInverse">@style/TextAppearance.Quantum.Inverse</item>
 
         <item name="textColorPrimary">@color/primary_text_quantum_light</item>
         <item name="textColorPrimaryInverse">@color/primary_text_quantum_dark</item>
@@ -411,16 +411,16 @@
         <item name="textColorSearchUrl">@color/search_url_text_quantum_light</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_quantum_light</item>
 
-        <item name="textAppearanceLarge">@style/TextAppearance.Quantum.Light.Large</item>
-        <item name="textAppearanceLargeInverse">@style/TextAppearance.Quantum.Light.Large.Inverse</item>
-        <item name="textAppearanceMedium">@style/TextAppearance.Quantum.Light.Medium</item>
-        <item name="textAppearanceMediumInverse">@style/TextAppearance.Quantum.Light.Medium.Inverse</item>
-        <item name="textAppearanceSmall">@style/TextAppearance.Quantum.Light.Small</item>
-        <item name="textAppearanceSmallInverse">@style/TextAppearance.Quantum.Light.Small.Inverse</item>
-        <item name="textAppearanceSearchResultTitle">@style/TextAppearance.Quantum.Light.SearchResult.Title</item>
-        <item name="textAppearanceSearchResultSubtitle">@style/TextAppearance.Quantum.Light.SearchResult.Subtitle</item>
+        <item name="textAppearanceLarge">@style/TextAppearance.Quantum.Large</item>
+        <item name="textAppearanceLargeInverse">@style/TextAppearance.Quantum.Large.Inverse</item>
+        <item name="textAppearanceMedium">@style/TextAppearance.Quantum.Medium</item>
+        <item name="textAppearanceMediumInverse">@style/TextAppearance.Quantum.Medium.Inverse</item>
+        <item name="textAppearanceSmall">@style/TextAppearance.Quantum.Small</item>
+        <item name="textAppearanceSmallInverse">@style/TextAppearance.Quantum.Small.Inverse</item>
+        <item name="textAppearanceSearchResultTitle">@style/TextAppearance.Quantum.SearchResult.Title</item>
+        <item name="textAppearanceSearchResultSubtitle">@style/TextAppearance.Quantum.SearchResult.Subtitle</item>
 
-        <item name="textAppearanceButton">@style/TextAppearance.Quantum.Light.Widget.Button</item>
+        <item name="textAppearanceButton">@style/TextAppearance.Quantum.Widget.Button</item>
 
         <item name="editTextColor">?attr/textColorPrimary</item>
         <item name="editTextBackground">@drawable/edit_text_quantum</item>
@@ -430,8 +430,8 @@
         <item name="textCheckMark">@drawable/indicator_check_mark_light</item>
         <item name="textCheckMarkInverse">@drawable/indicator_check_mark_dark</item>
 
-        <item name="textAppearanceLargePopupMenu">@style/TextAppearance.Quantum.Light.Widget.PopupMenu.Large</item>
-        <item name="textAppearanceSmallPopupMenu">@style/TextAppearance.Quantum.Light.Widget.PopupMenu.Small</item>
+        <item name="textAppearanceLargePopupMenu">@style/TextAppearance.Quantum.Widget.PopupMenu.Large</item>
+        <item name="textAppearanceSmallPopupMenu">@style/TextAppearance.Quantum.Widget.PopupMenu.Small</item>
 
         <!-- Button styles -->
         <item name="buttonStyle">@style/Widget.Quantum.Light.Button</item>
@@ -606,7 +606,7 @@
         <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.Quantum.QuickContactBadgeSmall.WindowLarge</item>
         <item name="listPopupWindowStyle">@style/Widget.Quantum.Light.ListPopupWindow</item>
         <item name="popupMenuStyle">@style/Widget.Quantum.Light.PopupMenu</item>
-        <item name="stackViewStyle">@style/Widget.Quantum.StackView</item>
+        <item name="stackViewStyle">@style/Widget.Quantum.Light.StackView</item>
         <item name="activityChooserViewStyle">@style/Widget.Quantum.Light.ActivityChooserView</item>
         <item name="fragmentBreadCrumbsStyle">@style/Widget.Quantum.Light.FragmentBreadCrumbs</item>
 
@@ -690,10 +690,10 @@
         <item name="timePickerHeaderBackgroundColor">?attr/colorBackground</item>
 
         <!-- TimePicker Header time label text appearance -->
-        <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Quantum.Light.TimePicker.TimeLabel</item>
+        <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Quantum.TimePicker.TimeLabel</item>
 
         <!-- TimePicker Header am pm label text appearance -->
-        <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.Quantum.Light.TimePicker.AmPmLabel</item>
+        <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.Quantum.TimePicker.AmPmLabel</item>
 
         <!-- TimePicker dialog theme -->
         <item name="timePickerDialogTheme">@style/Theme.Quantum.Light.Dialog.TimePicker</item>
@@ -717,9 +717,6 @@
         <item name="colorControlActivated">?attr/colorPrimary</item>
         <item name="colorButtonNormal">@color/quantum_grey_100</item>
         <item name="colorButtonPressed">@color/quantum_grey_500</item>
-        <!-- TODO: Remove these attrs and move into button style. -->
-        <item name="colorButtonNormalColored">?attr/colorPrimary</item>
-        <item name="colorButtonPressedColored">?attr/colorPrimaryDark</item>
     </style>
 
     <style name="ThemeOverlay" />
@@ -856,6 +853,14 @@
         <item name="imeExtractExitAnimation">@anim/input_method_extract_exit</item>
     </style>
 
+    <!-- Default theme for quantum style voice interaction, which is used by the
+         {@link android.service.voice.VoiceInteractionSession} class.
+         this inherits from Theme.Panel, but sets up appropriate animations
+         and a few custom attributes. -->
+    <style name="Theme.Quantum.VoiceInteractionSession" parent="Theme.Quantum.Light.Panel">
+        <item name="android:windowAnimationStyle">@android:style/Animation.VoiceInteractionSession</item>
+    </style>
+
     <!-- Theme for the search input bar. -->
 
     <style name="Theme.Quantum.SearchBar" parent="Theme.Quantum.Panel">
@@ -1031,8 +1036,8 @@
         <item name="buttonBarStyle">@style/Widget.Quantum.Light.ButtonBar.AlertDialog</item>
         <item name="borderlessButtonStyle">@style/Widget.Quantum.Light.Button.Borderless.Small</item>
 
-        <item name="textAppearance">@style/TextAppearance.Quantum.Light</item>
-        <item name="textAppearanceInverse">@style/TextAppearance.Quantum.Light.Inverse</item>
+        <item name="textAppearance">@style/TextAppearance.Quantum</item>
+        <item name="textAppearanceInverse">@style/TextAppearance.Quantum.Inverse</item>
 
         <item name="listPreferredItemPaddingLeft">16dip</item>
         <item name="listPreferredItemPaddingRight">16dip</item>
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
index 0cd19f2..67203b2 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
@@ -64,6 +64,8 @@
             unpairAll();
         } else if ("getName".equals(command)) {
             getName();
+        } else if ("getAddress".equals(command)) {
+            getAddress();
         } else {
             finish(null);
         }
@@ -90,6 +92,12 @@
         finish(mSuccessResult);
     }
 
+    public void getAddress() {
+        String name = getBluetoothAdapter().getAddress();
+        mSuccessResult.putString("address", name);
+        finish(mSuccessResult);
+    }
+
     public void finish(Bundle result) {
         if (result == null) {
             result = new Bundle();
diff --git a/core/tests/coretests/src/android/net/RssiCurveTest.java b/core/tests/coretests/src/android/net/RssiCurveTest.java
new file mode 100644
index 0000000..d4438df
--- /dev/null
+++ b/core/tests/coretests/src/android/net/RssiCurveTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import junit.framework.TestCase;
+
+public class RssiCurveTest extends TestCase {
+    public void testLookupScore_constantCurve() {
+        RssiCurve curve = new RssiCurve(-100, 200, new byte[] { 10 });
+        assertEquals(10, curve.lookupScore(-200));
+        assertEquals(10, curve.lookupScore(-100));
+        assertEquals(10, curve.lookupScore(0));
+        assertEquals(10, curve.lookupScore(100));
+        assertEquals(10, curve.lookupScore(200));
+    }
+
+    public void testLookupScore_changingCurve() {
+        RssiCurve curve = new RssiCurve(-100, 100, new byte[] { -10, 10 });
+        assertEquals(-10, curve.lookupScore(-200));
+        assertEquals(-10, curve.lookupScore(-100));
+        assertEquals(-10, curve.lookupScore(-50));
+        assertEquals(10, curve.lookupScore(0));
+        assertEquals(10, curve.lookupScore(50));
+        assertEquals(10, curve.lookupScore(100));
+        assertEquals(10, curve.lookupScore(200));
+    }
+}
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
index b0b119b..9029ba5 100755
--- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -21,4 +21,4 @@
   $COMMAND
 fi
 
-adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
+adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest,android.os.InputMethodSubtypeSwitchingControllerTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
new file mode 100644
index 0000000..6d33529
--- /dev/null
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+
+import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
+import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTestCase {
+    final private static String DUMMY_PACKAGE_NAME = "dymmy package name";
+    final private static String DUMMY_SETTING_ACTIVITY_NAME = "";
+    final private static boolean DUMMY_IS_AUX_IME = false;
+    final private static boolean DUMMY_FORCE_DEFAULT = false;
+    final private static int DUMMY_IS_DEFAULT_RES_ID = 0;
+    final private static String SYSTEM_LOCALE = "en_US";
+
+    private static InputMethodSubtype createDummySubtype(final String locale) {
+        final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder();
+        return builder.setSubtypeNameResId(0)
+                .setSubtypeIconResId(0)
+                .setSubtypeLocale(locale)
+                .setIsAsciiCapable(true)
+                .build();
+    }
+
+    private static void addDummyImeSubtypeListItems(List<ImeSubtypeListItem> items,
+            String imeName, String imeLabel, List<String> subtypeLocales,
+            boolean supportsSwitchingToNextInputMethod) {
+        final ResolveInfo ri = new ResolveInfo();
+        final ServiceInfo si = new ServiceInfo();
+        final ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = DUMMY_PACKAGE_NAME;
+        ai.enabled = true;
+        si.applicationInfo = ai;
+        si.enabled = true;
+        si.packageName = DUMMY_PACKAGE_NAME;
+        si.name = imeName;
+        si.exported = true;
+        si.nonLocalizedLabel = imeLabel;
+        ri.serviceInfo = si;
+        final List<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        for (String subtypeLocale : subtypeLocales) {
+            subtypes.add(createDummySubtype(subtypeLocale));
+        }
+        final InputMethodInfo imi = new InputMethodInfo(ri, DUMMY_IS_AUX_IME,
+                DUMMY_SETTING_ACTIVITY_NAME, subtypes, DUMMY_IS_DEFAULT_RES_ID,
+                DUMMY_FORCE_DEFAULT, supportsSwitchingToNextInputMethod);
+        for (int i = 0; i < subtypes.size(); ++i) {
+            final String subtypeLocale = subtypeLocales.get(i);
+            final InputMethodSubtype subtype = subtypes.get(i);
+            items.add(new ImeSubtypeListItem(imeName, subtypeLocale, imi, i, subtypeLocale,
+                    SYSTEM_LOCALE));
+        }
+    }
+
+    private static List<ImeSubtypeListItem> createTestData() {
+        final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
+        addDummyImeSubtypeListItems(items, "switchAwareLatinIme", "switchAwareLatinIme",
+                Arrays.asList("en_US", "es_US", "fr"),
+                true /* supportsSwitchingToNextInputMethod*/);
+        addDummyImeSubtypeListItems(items, "nonSwitchAwareLatinIme", "nonSwitchAwareLatinIme",
+                Arrays.asList("en_UK", "hi"),
+                false /* supportsSwitchingToNextInputMethod*/);
+        addDummyImeSubtypeListItems(items, "switchAwareJapaneseIme", "switchAwareJapaneseIme",
+                Arrays.asList("ja_JP"),
+                true /* supportsSwitchingToNextInputMethod*/);
+        addDummyImeSubtypeListItems(items, "nonSwitchAwareJapaneseIme", "nonSwitchAwareJapaneseIme",
+                Arrays.asList("ja_JP"),
+                false /* supportsSwitchingToNextInputMethod*/);
+        return items;
+    }
+
+    @SmallTest
+    public void testGetNextInputMethodImplWithNotOnlyCurrentIme() throws Exception {
+        final List<ImeSubtypeListItem> imList = createTestData();
+
+        final boolean ONLY_CURRENT_IME = false;
+        ImeSubtypeListItem currentIme;
+        ImeSubtypeListItem nextIme;
+
+        // "switchAwareLatinIme/en_US" -> "switchAwareLatinIme/es_US"
+        currentIme = imList.get(0);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(1), nextIme);
+        // "switchAwareLatinIme/es_US" -> "switchAwareLatinIme/fr"
+        currentIme = imList.get(1);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(2), nextIme);
+        // "switchAwareLatinIme/fr" -> "nonSwitchAwareLatinIme/en_UK
+        currentIme = imList.get(2);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(3), nextIme);
+        // "nonSwitchAwareLatinIme/en_UK" -> "nonSwitchAwareLatinIme/hi"
+        currentIme = imList.get(3);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(4), nextIme);
+        // "nonSwitchAwareLatinIme/hi" -> "switchAwareJapaneseIme/ja_JP"
+        currentIme = imList.get(4);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(5), nextIme);
+        // "switchAwareJapaneseIme/ja_JP" -> "nonSwitchAwareJapaneseIme/ja_JP"
+        currentIme = imList.get(5);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(6), nextIme);
+        // "nonSwitchAwareJapaneseIme/ja_JP" -> "switchAwareLatinIme/en_US"
+        currentIme = imList.get(6);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(0), nextIme);
+    }
+
+    @SmallTest
+    public void testGetNextInputMethodImplWithOnlyCurrentIme() throws Exception {
+        final List<ImeSubtypeListItem> imList = createTestData();
+
+        final boolean ONLY_CURRENT_IME = true;
+        ImeSubtypeListItem currentIme;
+        ImeSubtypeListItem nextIme;
+
+        // "switchAwareLatinIme/en_US" -> "switchAwareLatinIme/es_US"
+        currentIme = imList.get(0);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(1), nextIme);
+        // "switchAwareLatinIme/es_US" -> "switchAwareLatinIme/fr"
+        currentIme = imList.get(1);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(2), nextIme);
+        // "switchAwareLatinIme/fr" -> "switchAwareLatinIme/en_US"
+        currentIme = imList.get(2);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(0), nextIme);
+
+        // "nonSwitchAwareLatinIme/en_UK" -> "nonSwitchAwareLatinIme/hi"
+        currentIme = imList.get(3);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(4), nextIme);
+        // "nonSwitchAwareLatinIme/hi" -> "switchAwareLatinIme/en_UK"
+        currentIme = imList.get(4);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(3), nextIme);
+
+        // "switchAwareJapaneseIme/ja_JP" -> null
+        currentIme = imList.get(5);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertNull(nextIme);
+
+        // "nonSwitchAwareJapaneseIme/ja_JP" -> null
+        currentIme = imList.get(6);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertNull(nextIme);
+    }
+ }
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 01d22ee..1ef74ba 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -492,11 +492,11 @@
 }
 
 key BUTTON_X {
-    base:                               fallback DPAD_CENTER
+    base:                               fallback DEL
 }
 
 key BUTTON_Y {
-    base:                               fallback BACK
+    base:                               fallback SPACE
 }
 
 key BUTTON_Z {
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 56423c9..cfc1484 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -404,6 +404,8 @@
 # key 503 KEY_BRL_DOT7
 # key 504 KEY_BRL_DOT8
 
+key 580   APP_SWITCH
+
 # Keys defined by HID usages
 key usage 0x0c006F BRIGHTNESS_UP
 key usage 0x0c0070 BRIGHTNESS_DOWN
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 92ecd24..bddb8ec 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 April 1, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on May 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 April 1, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on May 1, 2014.
 <br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
 
 
@@ -111,7 +111,7 @@
 
 
 <img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chf=bg%2Cs%2C00000000&chd=t%3A0.1%2C93.5%2C6.4&chco=c4df9b%2C6fad0c&chs=400x250&cht=p" />
+src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A0.1%2C87.0%2C12.9&chf=bg%2Cs%2C00000000&chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
 
 <p>To declare which version of OpenGL ES your application requires, you should use the {@code
 android:glEsVersion} attribute of the <a
@@ -133,17 +133,17 @@
 </tr>
 <tr>
 <td>2.0</th>
-<td>89.4%</td>
+<td>87.0%</td>
 </tr>
 <tr>
 <td>3.0</th>
-<td>10.5%</td>
+<td>12.9%</td>
 </tr>
 </table>
 
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on May 1, 2014</em></p>
 
 
 
@@ -161,17 +161,17 @@
 var VERSION_DATA =
 [
   {
-    "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",
+    "chart": "//chart.googleapis.com/chart?chs=500x250&cht=p&chd=t%3A1.0%2C16.2%2C0.1%2C13.4%2C60.8%2C8.5&chf=bg%2Cs%2C00000000&chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chco=c4df9b%2C6fad0c",
     "data": [
       {
         "api": 8,
         "name": "Froyo",
-        "perc": "1.1"
+        "perc": "1.0"
       },
       {
         "api": 10,
         "name": "Gingerbread",
-        "perc": "17.8"
+        "perc": "16.2"
       },
       {
         "api": 13,
@@ -181,27 +181,27 @@
       {
         "api": 15,
         "name": "Ice Cream Sandwich",
-        "perc": "14.3"
+        "perc": "13.4"
       },
       {
         "api": 16,
         "name": "Jelly Bean",
-        "perc": "34.4"
+        "perc": "33.5"
       },
       {
         "api": 17,
         "name": "Jelly Bean",
-        "perc": "18.1"
+        "perc": "18.8"
       },
       {
         "api": 18,
         "name": "Jelly Bean",
-        "perc": "8.9"
+        "perc": "8.5"
       },
       {
         "api": 19,
         "name": "KitKat",
-        "perc": "5.3"
+        "perc": "8.5"
       }
     ]
   }
@@ -217,19 +217,19 @@
     "data": {
       "Large": {
         "hdpi": "0.6",
-        "ldpi": "0.7",
+        "ldpi": "0.6",
         "mdpi": "4.4",
-        "tvdpi": "1.5",
+        "tvdpi": "1.6",
         "xhdpi": "0.6"
       },
       "Normal": {
-        "hdpi": "33.7",
-        "mdpi": "13.2",
-        "xhdpi": "19.8",
-        "xxhdpi": "12.5"
+        "hdpi": "33.9",
+        "mdpi": "12.5",
+        "xhdpi": "19.9",
+        "xxhdpi": "13.5"
       },
       "Small": {
-        "ldpi": "8.1"
+        "ldpi": "7.5"
       },
       "Xlarge": {
         "hdpi": "0.3",
@@ -238,8 +238,8 @@
         "xhdpi": "0.3"
       }
     },
-    "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"
+    "densitychart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A8.2%2C21.1%2C1.6%2C34.8%2C20.8%2C13.5&chf=bg%2Cs%2C00000000&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chco=c4df9b%2C6fad0c",
+    "layoutchart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A4.9%2C7.8%2C80.0%2C7.5&chf=bg%2Cs%2C00000000&chl=Xlarge%7CLarge%7CNormal%7CSmall&chco=c4df9b%2C6fad0c"
   }
 ];
 
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index 071492d..8ea5e7e 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -253,36 +253,36 @@
     <td>Windows</td>
     <td>
   <a onclick="return onDownload(this)" id="win-studio"
-      href="http://dl.google.com/android/studio/install/0.4.6/android-studio-bundle-133.1028713-windows.exe">
-      android-studio-bundle-133.1028713-windows.exe
+      href="http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-windows.exe">
+      android-studio-bundle-135.1078000-windows.exe
       </a>
     </td>
-    <td>519592042 bytes</td>
-    <td>9029c18738a75830786326d62c96d557</td>
+    <td>519082997 bytes</td>
+    <td>ac69889210c4d02ee3ccc1c0f3c5cf3c</td>
   </tr>
 
   <tr>
     <td><nobr>Mac OS X</nobr></td>
     <td>
   <a onclick="return onDownload(this)" id="mac-studio"
-    href="http://dl.google.com/android/studio/install/0.4.6/android-studio-bundle-133.1028713-mac.dmg">
-    android-studio-bundle-133.1028713-mac.dmg
+    href="http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-mac.dmg">
+    android-studio-bundle-135.1078000-mac.dmg
     </a>
     </td>
-    <td>497595811 bytes</td>
-    <td>eb2474e6d17537ddfa535e6fe8adcf0d</td>
+    <td>495989974 bytes</td>
+    <td>8c7b1ef376b8ca206c99823d9e8fd54d</td>
   </tr>
 
   <tr>
     <td>Linux</td>
     <td>
   <a onclick="return onDownload(this)" id="linux-studio"
-    href="http://dl.google.com/android/studio/install/0.4.6/android-studio-bundle-133.1028713-linux.tgz">
-    android-studio-bundle-133.1028713-linux.tgz
+    href="http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-linux.tgz">
+    android-studio-bundle-135.1078000-linux.tgz
     </a>
     </td>
-    <td>522177460 bytes</td>
-    <td>cc847dd6249b3033737dabe0377c8c66</td>
+    <td>520523870 bytes</td>
+    <td>689238d5e632fd236b13f9c6d49f0cb4</td>
   </tr>
   </table>
 
@@ -430,6 +430,19 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>Android Studio v0.5.2</a> <em>(May 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+  <ul>
+    <li>See <a href="http://tools.android.com/recent">tools.android.com</a> for a full list of changes.</li>
+  </ul>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>Android Studio v0.4.6</a> <em>(March 2014)</em>
   </p>
 
@@ -650,7 +663,7 @@
   if (os) {
     /* set up primary ACE download button */
     $('#download-ide-button').show();
-    $('#download-ide-button').append("Download Android Studio <span class='small'>v0.4.6</span>"
+    $('#download-ide-button').append("Download Android Studio <span class='small'>v0.5.2</span>"
         + "<br/> <span class='small'>for " + os + "</span>");
     $('#download-ide-button').click(function() {return onDownload(this,true);}).attr('href', bundlename);
 
diff --git a/docs/html/tools/device.jd b/docs/html/tools/device.jd
index ccd5903..e9caa44 100644
--- a/docs/html/tools/device.jd
+++ b/docs/html/tools/device.jd
@@ -192,6 +192,10 @@
     <td><code>12d1</code></td>
   </tr>
   <tr>
+    <td>Intel</td>
+    <td><code>8087</code></td>
+  </tr>
+  <tr>
     <td>K-Touch</td>
     <td><code>24e3</code></td>
   </tr>
diff --git a/graphics/java/android/graphics/CanvasProperty.java b/graphics/java/android/graphics/CanvasProperty.java
new file mode 100644
index 0000000..99ea9b1
--- /dev/null
+++ b/graphics/java/android/graphics/CanvasProperty.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+/**
+ * TODO: Make public?
+ * @hide
+ */
+public final class CanvasProperty<T> {
+    private long mNativeContainer;
+
+    public static CanvasProperty<Float> createFloat(float initialValue) {
+        return new CanvasProperty<Float>(nCreateFloat(initialValue));
+    }
+
+    public static CanvasProperty<Paint> createPaint(Paint initialValue) {
+        return new CanvasProperty<Paint>(nCreatePaint(initialValue.mNativePaint));
+    }
+
+    private CanvasProperty(long nativeContainer) {
+        mNativeContainer = nativeContainer;
+    }
+
+    /** @hide */
+    public long getNativeContainer() {
+        return mNativeContainer;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            nUnref(mNativeContainer);
+            mNativeContainer = 0;
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private static native long nCreateFloat(float initialValue);
+    private static native long nCreatePaint(long initialValuePaintPtr);
+    private static native void nUnref(long ptr);
+}
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index e08ed50..062acaf 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -253,4 +253,31 @@
         }
         return -1;
     }
+
+    /**
+     * Determine whether or not this is a public-visible {@code format}.
+     *
+     * <p>In particular, {@code @hide} formats will return {@code false}.</p>
+     *
+     * <p>Any other formats (including UNKNOWN) will return {@code false}.</p>
+     *
+     * @param format an integer format
+     * @return a boolean
+     *
+     * @hide
+     */
+    public static boolean isPublicFormat(int format) {
+        switch (format) {
+            case RGB_565:
+            case NV16:
+            case YUY2:
+            case YV12:
+            case NV21:
+            case YUV_420_888:
+            case RAW_SENSOR:
+                return true;
+        }
+
+        return false;
+    }
 }
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index d96d6d8..832b9c3 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -115,7 +115,7 @@
                 info.bytesPerPixel = 1;
                 break;
             default:
-                throw new IllegalArgumentException("unkonwon pixel format " + format);
+                throw new IllegalArgumentException("unknown pixel format " + format);
         }
     }
 
@@ -135,4 +135,29 @@
 
     public int  bytesPerPixel;
     public int  bitsPerPixel;
+
+    /**
+     * Determine whether or not this is a public-visible and non-deprecated {@code format}.
+     *
+     * <p>In particular, {@code @hide} formats will return {@code false}.</p>
+     *
+     * <p>Any other indirect formats (such as {@code TRANSPARENT} or {@code TRANSLUCENT})
+     * will return {@code false}.</p>
+     *
+     * @param format an integer format
+     * @return a boolean
+     *
+     * @hide
+     */
+    public static boolean isPublicFormat(int format) {
+        switch (format) {
+            case RGBA_8888:
+            case RGBX_8888:
+            case RGB_888:
+            case RGB_565:
+                return true;
+        }
+
+        return false;
+    }
 }
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index e3f57e9..218a057 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -16,20 +16,22 @@
 
 package android.graphics.drawable;
 
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
 import android.graphics.Rect;
-import android.util.MathUtils;
-import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
 
 /**
  * Draws a Quantum Paper ripple.
  */
 class Ripple {
-    private static final TimeInterpolator INTERPOLATOR = new DecelerateInterpolator(2.0f);
+    private static final TimeInterpolator INTERPOLATOR = new DecelerateInterpolator();
 
     /** Starting radius for a ripple. */
     private static final int STARTING_RADIUS_DP = 16;
@@ -37,6 +39,9 @@
     /** Radius when finger is outside view bounds. */
     private static final int OUTSIDE_RADIUS_DP = 16;
 
+    /** Radius when finger is inside view bounds. */
+    private static final int INSIDE_RADIUS_DP = 96;
+
     /** Margin when constraining outside touches (fraction of outer radius). */
     private static final float OUTSIDE_MARGIN = 0.8f;
 
@@ -44,15 +49,53 @@
     private static final float OUTSIDE_RESISTANCE = 0.7f;
 
     /** Minimum alpha value during a pulse animation. */
-    private static final int PULSE_MIN_ALPHA = 128;
+    private static final float PULSE_MIN_ALPHA = 0.5f;
 
+    /** Duration for animating the trailing edge of the ripple. */
+    private static final int EXIT_DURATION = 600;
+
+    /** Duration for animating the leading edge of the ripple. */
+    private static final int ENTER_DURATION = 400;
+
+    /** Duration for animating the ripple alpha in and out. */
+    private static final int FADE_DURATION = 50;
+
+    /** Minimum elapsed time between start of enter and exit animations. */
+    private static final int EXIT_MIN_DELAY = 200;
+
+    /** Duration for animating between inside and outside touch. */
+    private static final int OUTSIDE_DURATION = 300;
+
+    /** Duration for animating pulses. */
+    private static final int PULSE_DURATION = 400;
+
+    /** Interval between pulses while inside and fully entered. */
+    private static final int PULSE_INTERVAL = 400;
+
+    /** Delay before pulses start. */
+    private static final int PULSE_DELAY = 500;
+
+    private final Drawable mOwner;
+
+    /** Bounds used for computing max radius and containment. */
     private final Rect mBounds;
-    private final Rect mPadding;
 
-    private RippleAnimator mAnimator;
+    /** Configured maximum ripple radius when the center is outside the bounds. */
+    private final int mMaxOutsideRadius;
 
-    private int mMinRadius;
-    private int mOutsideRadius;
+    /** Configured maximum ripple radius. */
+    private final int mMaxInsideRadius;
+
+    private ObjectAnimator mOuter;
+    private ObjectAnimator mInner;
+    private ObjectAnimator mAlpha;
+
+    /** Maximum ripple radius. */
+    private int mMaxRadius;
+
+    private float mOuterRadius;
+    private float mInnerRadius;
+    private float mAlphaMultiplier;
 
     /** Center x-coordinate. */
     private float mX;
@@ -61,46 +104,151 @@
     private float mY;
 
     /** Whether the center is within the parent bounds. */
-    private boolean mInside;
+    private boolean mInsideBounds;
 
     /** Whether to pulse this ripple. */
-    boolean mPulse;
-    
-    /** Enter state. A value in [0...1] or -1 if not set. */
-    float mEnterState = -1;
+    private boolean mPulseEnabled;
 
-    /** Exit state. A value in [0...1] or -1 if not set. */
-    float mExitState = -1;
+    /** Temporary hack since we can't check finished state of animator. */
+    private boolean mExitFinished;
 
-    /** Outside state. A value in [0...1] or -1 if not set. */
-    float mOutsideState = -1;
-
-    /** Pulse state. A value in [0...1] or -1 if not set. */
-    float mPulseState = -1;
+    /** Whether this ripple has ever moved. */
+    private boolean mHasMoved;
 
     /**
-     * Creates a new ripple with the specified parent bounds, padding, initial
-     * position, and screen density.
+     * Creates a new ripple.
      */
-    public Ripple(Rect bounds, Rect padding, float x, float y, float density, boolean pulse) {
+    public Ripple(Drawable owner, Rect bounds, float density, boolean pulseEnabled) {
+        mOwner = owner;
         mBounds = bounds;
-        mPadding = padding;
-        mInside = mBounds.contains((int) x, (int) y);
-        mPulse = pulse;
+        mPulseEnabled = pulseEnabled;
 
-        mX = x;
-        mY = y;
+        mOuterRadius = (int) (density * STARTING_RADIUS_DP + 0.5f);
+        mMaxOutsideRadius = (int) (density * OUTSIDE_RADIUS_DP + 0.5f);
+        mMaxInsideRadius = (int) (density * INSIDE_RADIUS_DP + 0.5f);
+        mMaxRadius = Math.min(mMaxInsideRadius, Math.max(bounds.width(), bounds.height()));
+    }
 
-        mMinRadius = (int) (density * STARTING_RADIUS_DP + 0.5f);
-        mOutsideRadius = (int) (density * OUTSIDE_RADIUS_DP + 0.5f);
+    public void setOuterRadius(float r) {
+        mOuterRadius = r;
+        invalidateSelf();
     }
-    
-    public void setMinRadius(int minRadius) {
-        mMinRadius = minRadius;
+
+    public float getOuterRadius() {
+        return mOuterRadius;
     }
-    
-    public void setOutsideRadius(int outsideRadius) {
-        mOutsideRadius = outsideRadius;
+
+    public void setInnerRadius(float r) {
+        mInnerRadius = r;
+        invalidateSelf();
+    }
+
+    public float getInnerRadius() {
+        return mInnerRadius;
+    }
+
+    public void setAlphaMultiplier(float a) {
+        mAlphaMultiplier = a;
+        invalidateSelf();
+    }
+
+    public float getAlphaMultiplier() {
+        return mAlphaMultiplier;
+    }
+
+    /**
+     * Returns whether this ripple has finished exiting.
+     */
+    public boolean isFinished() {
+        return mExitFinished;
+    }
+
+    /**
+     * Called when the bounds change.
+     */
+    public void onBoundsChanged() {
+        mMaxRadius = Math.min(mMaxInsideRadius, Math.max(mBounds.width(), mBounds.height()));
+
+        updateInsideBounds();
+    }
+
+    private void updateInsideBounds() {
+        final boolean insideBounds = mBounds.contains((int) (mX + 0.5f), (int) (mY + 0.5f));
+        if (mInsideBounds != insideBounds || !mHasMoved) {
+            mInsideBounds = insideBounds;
+            mHasMoved = true;
+
+            if (insideBounds) {
+                enter();
+            } else {
+                outside();
+            }
+        }
+    }
+
+    /**
+     * Draws the ripple using the specified paint.
+     */
+    public boolean draw(Canvas c, Paint p) {
+        final Rect bounds = mBounds;
+        final float outerRadius = mOuterRadius;
+        final float innerRadius = mInnerRadius;
+        final float alphaMultiplier = mAlphaMultiplier;
+
+        // Cache the paint alpha so we can restore it later.
+        final int paintAlpha = p.getAlpha();
+        final int alpha = (int) (paintAlpha * alphaMultiplier + 0.5f);
+
+        // Apply resistance effect when outside bounds.
+        final float x;
+        final float y;
+        if (mInsideBounds) {
+            x = mX;
+            y = mY;
+        } else {
+            // TODO: We need to do this outside of draw() so that our dirty
+            // bounds accurately reflect resistance.
+            x = looseConstrain(mX, bounds.left, bounds.right,
+                    mOuterRadius * OUTSIDE_MARGIN, OUTSIDE_RESISTANCE);
+            y = looseConstrain(mY, bounds.top, bounds.bottom,
+                    mOuterRadius * OUTSIDE_MARGIN, OUTSIDE_RESISTANCE);
+        }
+
+        final boolean hasContent;
+        if (alphaMultiplier <= 0 || innerRadius >= outerRadius) {
+            // Nothing to draw.
+            hasContent = false;
+        } else if (innerRadius > 0) {
+            // Draw a ring.
+            final float strokeWidth = outerRadius - innerRadius;
+            final float strokeRadius = innerRadius + strokeWidth / 2.0f;
+            p.setAlpha(alpha);
+            p.setStyle(Style.STROKE);
+            p.setStrokeWidth(strokeWidth);
+            c.drawCircle(x, y, strokeRadius, p);
+            hasContent = true;
+        } else if (outerRadius > 0) {
+            // Draw a circle.
+            p.setAlpha(alpha);
+            p.setStyle(Style.FILL);
+            c.drawCircle(x, y, outerRadius, p);
+            hasContent = true;
+        } else {
+            hasContent = false;
+        }
+
+        p.setAlpha(paintAlpha);
+        return hasContent;
+    }
+
+    /**
+     * Returns the maximum bounds for this ripple.
+     */
+    public void getBounds(Rect bounds) {
+        final int x = (int) mX;
+        final int y = (int) mY;
+        final int maxRadius = mMaxRadius;
+        bounds.set(x - maxRadius, y - maxRadius, x + maxRadius, y + maxRadius);
     }
 
     /**
@@ -110,117 +258,116 @@
         mX = x;
         mY = y;
 
-        final boolean inside = mBounds.contains((int) x, (int) y);
-        if (mInside != inside) {
-            if (mAnimator != null) {
-                mAnimator.outside();
-            }
-            mInside = inside;
+        updateInsideBounds();
+        invalidateSelf();
+    }
+
+    /**
+     * Starts the exit animation. If {@link #enter()} was called recently, the
+     * animation may be postponed.
+     */
+    public void exit() {
+        mExitFinished = false;
+
+        final ObjectAnimator inner = ObjectAnimator.ofFloat(this, "innerRadius", 0, mMaxRadius);
+        inner.setAutoCancel(true);
+        inner.setDuration(EXIT_DURATION);
+        inner.setInterpolator(INTERPOLATOR);
+        inner.addListener(mAnimationListener);
+
+        if (mOuter != null && mOuter.isStarted()) {
+            // If we haven't been running the enter animation for long enough,
+            // delay the exit animator.
+            final int elapsed = (int) (mOuter.getAnimatedFraction() * mOuter.getDuration());
+            final int delay = Math.max(0, EXIT_MIN_DELAY - elapsed);
+            inner.setStartDelay(delay);
+        }
+
+        inner.start();
+
+        final ObjectAnimator alpha = ObjectAnimator.ofFloat(this, "alphaMultiplier", 0);
+        alpha.setAutoCancel(true);
+        alpha.setDuration(EXIT_DURATION);
+        alpha.start();
+
+        mInner = inner;
+        mAlpha = alpha;
+    }
+
+    /**
+     * Cancel all animations.
+     */
+    public void cancel() {
+        if (mInner != null) {
+            mInner.cancel();
+        }
+
+        if (mOuter != null) {
+            mOuter.cancel();
+        }
+
+        if (mAlpha != null) {
+            mAlpha.cancel();
         }
     }
 
-    public void onBoundsChanged() {
-        final boolean inside = mBounds.contains((int) mX, (int) mY);
-        if (mInside != inside) {
-            if (mAnimator != null) {
-                mAnimator.outside();
-            }
-            mInside = inside;
-        }
+    private void invalidateSelf() {
+        mOwner.invalidateSelf();
     }
 
-    public RippleAnimator animate() {
-        if (mAnimator == null) {
-            mAnimator = new RippleAnimator(this);
-        }
-        return mAnimator;
-    }
+    /**
+     * Starts the enter animation.
+     */
+    private void enter() {
+        final ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerRadius", mMaxRadius);
+        outer.setAutoCancel(true);
+        outer.setDuration(ENTER_DURATION);
+        outer.setInterpolator(INTERPOLATOR);
+        outer.start();
 
-    public boolean draw(Canvas c, Paint p) {
-        final Rect bounds = mBounds;
-        final Rect padding = mPadding;
-        final float dX = Math.max(mX - bounds.left, bounds.right - mX);
-        final float dY = Math.max(mY - bounds.top, bounds.bottom - mY);
-        final int maxRadius = (int) Math.ceil(Math.sqrt(dX * dX + dY * dY));
+        final ObjectAnimator alpha = ObjectAnimator.ofFloat(this, "alphaMultiplier", 1);
+        if (mPulseEnabled) {
+            alpha.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    final ObjectAnimator pulse = ObjectAnimator.ofFloat(
+                            this, "alphaMultiplier", 1, PULSE_MIN_ALPHA);
+                    pulse.setAutoCancel(true);
+                    pulse.setDuration(PULSE_DURATION + PULSE_INTERVAL);
+                    pulse.setRepeatCount(ObjectAnimator.INFINITE);
+                    pulse.setRepeatMode(ObjectAnimator.REVERSE);
+                    pulse.setStartDelay(PULSE_DELAY);
+                    pulse.start();
 
-        final float enterState = mEnterState;
-        final float exitState = mExitState;
-        final float outsideState = mOutsideState;
-        final float pulseState = mPulseState;
-        final float insideRadius = MathUtils.lerp(mMinRadius, maxRadius, enterState);
-        final float outerRadius = MathUtils.lerp(mOutsideRadius, insideRadius,
-                mInside ? outsideState : 1 - outsideState);
-
-        // Apply resistance effect when outside bounds.
-        final float x = looseConstrain(mX, bounds.left + padding.left, bounds.right - padding.right,
-                outerRadius * OUTSIDE_MARGIN, OUTSIDE_RESISTANCE);
-        final float y = looseConstrain(mY, bounds.top + padding.top, bounds.bottom - padding.bottom,
-                outerRadius * OUTSIDE_MARGIN, OUTSIDE_RESISTANCE);
-
-        // Compute maximum alpha, taking pulse into account when active.
-        final int maxAlpha;
-        if (pulseState < 0 || pulseState >= 1) {
-            maxAlpha = 255;
-        } else {
-            final float pulseAlpha;
-            if (pulseState > 0.5) {
-                // Pulsing in to max alpha.
-                pulseAlpha = MathUtils.lerp(PULSE_MIN_ALPHA, 255, (pulseState - .5f) * 2);
-            } else {
-                // Pulsing out to min alpha.
-                pulseAlpha = MathUtils.lerp(255, PULSE_MIN_ALPHA, pulseState * 2f);
-            }
-
-            if (exitState > 0) {
-                // Animating exit, interpolate pulse with exit state.
-                maxAlpha = (int) (MathUtils.lerp(255, pulseAlpha, exitState) + 0.5f);
-            } else if (mInside) {
-                // No animation, no need to interpolate.
-                maxAlpha = (int) (pulseAlpha + 0.5f);
-            } else {
-                // Animating inside, interpolate pulse with inside state.
-                maxAlpha = (int) (MathUtils.lerp(pulseAlpha, 255, outsideState) + 0.5f);
-            }
-        }
-
-        if (maxAlpha > 0) {
-            if (exitState <= 0) {
-                // Exit state isn't showing, so we can simplify to a solid
-                // circle.
-                if (outerRadius > 0) {
-                    p.setAlpha(maxAlpha);
-                    p.setStyle(Style.FILL);
-                    c.drawCircle(x, y, outerRadius, p);
-                    return true;
+                    mAlpha = pulse;
                 }
-            } else {
-                // Both states are showing, so we need a circular stroke.
-                final float innerRadius = MathUtils.lerp(0, outerRadius, exitState);
-                final float strokeWidth = outerRadius - innerRadius;
-                if (strokeWidth > 0) {
-                    final float strokeRadius = innerRadius + strokeWidth / 2f;
-                    final int alpha = (int) (MathUtils.lerp(maxAlpha, 0, exitState) + 0.5f);
-                    if (alpha > 0) {
-                        p.setAlpha(alpha);
-                        p.setStyle(Style.STROKE);
-                        p.setStrokeWidth(strokeWidth);
-                        c.drawCircle(x, y, strokeRadius, p);
-                        return true;
-                    }
-                }
-            }
+            });
         }
+        alpha.setAutoCancel(true);
+        alpha.setDuration(FADE_DURATION);
+        alpha.start();
 
-        return false;
+        mOuter = outer;
+        mAlpha = alpha;
     }
 
-    public void getBounds(Rect bounds) {
-        final int x = (int) mX;
-        final int y = (int) mY;
-        final int dX = Math.max(x, mBounds.right - x);
-        final int dY = Math.max(x, mBounds.bottom - y);
-        final int maxRadius = (int) Math.ceil(Math.sqrt(dX * dX + dY * dY));
-        bounds.set(x - maxRadius, y - maxRadius, x + maxRadius, y + maxRadius);
+    /**
+     * Starts the outside transition animation.
+     */
+    private void outside() {
+        final ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerRadius", mMaxOutsideRadius);
+        outer.setAutoCancel(true);
+        outer.setDuration(OUTSIDE_DURATION);
+        outer.setInterpolator(INTERPOLATOR);
+        outer.start();
+
+        final ObjectAnimator alpha = ObjectAnimator.ofFloat(this, "alphaMultiplier", 1);
+        alpha.setAutoCancel(true);
+        alpha.setDuration(FADE_DURATION);
+        alpha.start();
+
+        mOuter = outer;
+        mAlpha = alpha;
     }
 
     /**
@@ -229,6 +376,7 @@
      */
     private static float looseConstrain(float value, float min, float max, float margin,
             float factor) {
+        // TODO: Can we use actual spring physics here?
         if (value < min) {
             return min - Math.min(margin, (float) Math.pow(min - value, factor));
         } else if (value > max) {
@@ -237,96 +385,16 @@
             return value;
         }
     }
-    
-    public static class RippleAnimator {
-        /** Duration for animating the trailing edge of the ripple. */
-        private static final int EXIT_DURATION = 600;
 
-        /** Duration for animating the leading edge of the ripple. */
-        private static final int ENTER_DURATION = 400;
-
-        /** Minimum elapsed time between start of enter and exit animations. */
-        private static final int EXIT_MIN_DELAY = 200;
-
-        /** Duration for animating between inside and outside touch. */
-        private static final int OUTSIDE_DURATION = 300;
-
-        /** Duration for animating pulses. */
-        private static final int PULSE_DURATION = 400;
-
-        /** Interval between pulses while inside and fully entered. */
-        private static final int PULSE_INTERVAL = 400;
-
-        /** Delay before pulses start. */
-        private static final int PULSE_DELAY = 500;
-
-        /** The target ripple being animated. */
-        private final Ripple mTarget;
-
-        /** When the ripple started appearing. */
-        private long mEnterTime = -1;
-
-        /** When the ripple started vanishing. */
-        private long mExitTime = -1;
-
-        /** When the ripple last transitioned between inside and outside touch. */
-        private long mOutsideTime = -1;
-
-        public RippleAnimator(Ripple target) {
-            mTarget = target;
-        }
-
-        /**
-         * Starts the enter animation.
-         */
-        public void enter() {
-            mEnterTime = AnimationUtils.currentAnimationTimeMillis();
-        }
-
-        /**
-         * Starts the exit animation. If {@link #enter()} was called recently, the
-         * animation may be postponed.
-         */
-        public void exit() {
-            final long minTime = mEnterTime + EXIT_MIN_DELAY;
-            mExitTime = Math.max(minTime, AnimationUtils.currentAnimationTimeMillis());
-        }
-
-        /**
-         * Starts the outside transition animation.
-         */
-        public void outside() {
-            mOutsideTime = AnimationUtils.currentAnimationTimeMillis();
-        }
-
-        /**
-         * Returns whether this ripple is currently animating.
-         */
-        public boolean isRunning() {
-            final long currentTime = AnimationUtils.currentAnimationTimeMillis();
-            return mEnterTime >= 0 && mEnterTime <= currentTime
-                    && (mExitTime < 0 || currentTime <= mExitTime + EXIT_DURATION);
-        }
-
-        public void update() {
-            // Track three states:
-            // - Enter: touch begins, affects outer radius
-            // - Outside: touch moves outside bounds, affects maximum outer radius
-            // - Exit: touch ends, affects inner radius
-            final long currentTime = AnimationUtils.currentAnimationTimeMillis();
-            mTarget.mEnterState = mEnterTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
-                    MathUtils.constrain((currentTime - mEnterTime) / (float) ENTER_DURATION, 0, 1));
-            mTarget.mExitState = mExitTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
-                    MathUtils.constrain((currentTime - mExitTime) / (float) EXIT_DURATION, 0, 1));
-            mTarget.mOutsideState = mOutsideTime < 0 ? 1 : INTERPOLATOR.getInterpolation(
-                    MathUtils.constrain((currentTime - mOutsideTime) / (float) OUTSIDE_DURATION, 0, 1));
-
-            // Pulse is a little more complicated.
-            if (mTarget.mPulse) {
-                final long pulseTime = (currentTime - mEnterTime - ENTER_DURATION - PULSE_DELAY);
-                mTarget.mPulseState = pulseTime < 0 ? -1
-                        : (pulseTime % (PULSE_INTERVAL + PULSE_DURATION)) / (float) PULSE_DURATION;
+    private final AnimatorListener mAnimationListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (animation == mInner) {
+                mExitFinished = true;
+                mOuterRadius = 0;
+                mInnerRadius = 0;
+                mAlphaMultiplier = 1;
             }
         }
-    }
+    };
 }
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index 0e8831f..0097183 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -27,8 +27,6 @@
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
-import android.graphics.drawable.Ripple.RippleAnimator;
-import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -40,7 +38,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
-import java.util.Arrays;
 
 /**
  * Documentation pending.
@@ -54,7 +51,6 @@
     private static final int MAX_RIPPLES = 10;
 
     private final Rect mTempRect = new Rect();
-    private final Rect mPaddingRect = new Rect();
 
     /** Current ripple effect bounds, used to constrain ripple effects. */
     private final Rect mHotspotBounds = new Rect();
@@ -68,14 +64,11 @@
     private final TouchFeedbackState mState;
 
     /** Lazily-created map of touch hotspot IDs to ripples. */
-    private SparseArray<Ripple> mTouchedRipples;
+    private SparseArray<Ripple> mRipples;
 
     /** Lazily-created array of actively animating ripples. */
-    private Ripple[] mActiveRipples;
-    private int mActiveRipplesCount = 0;
-
-    /** Lazily-created runnable for scheduling invalidation. */
-    private Runnable mAnimationRunnable;
+    private Ripple[] mAnimatingRipples;
+    private int mAnimatingRipplesCount = 0;
 
     /** Paint used to control appearance of ripples. */
     private Paint mRipplePaint;
@@ -86,9 +79,6 @@
     /** Target density of the display into which ripples are drawn. */
     private float mDensity = 1.0f;
 
-    /** Whether the animation runnable has been posted. */
-    private boolean mAnimating;
-
     /** Whether bounds are being overridden. */
     private boolean mOverrideBounds;
 
@@ -154,28 +144,19 @@
     private void onHotspotBoundsChange() {
         final int x = mHotspotBounds.centerX();
         final int y = mHotspotBounds.centerY();
-        final int N = mActiveRipplesCount;
+        final int N = mAnimatingRipplesCount;
         for (int i = 0; i < N; i++) {
             if (mState.mPinned) {
-                mActiveRipples[i].move(x, y);
+                mAnimatingRipples[i].move(x, y);
             }
-            mActiveRipples[i].onBoundsChanged();
+            mAnimatingRipples[i].onBoundsChanged();
         }
     }
 
     @Override
     public boolean setVisible(boolean visible, boolean restart) {
         if (!visible) {
-            if (mTouchedRipples != null) {
-                mTouchedRipples.clear();
-            }
-
-            if (mActiveRipplesCount > 0) {
-                Arrays.fill(mActiveRipples, null);
-                mActiveRipplesCount = 0;
-                mAnimating = false;
-                unscheduleSelf(mAnimationRunnable);
-            }
+            clearHotspots();
         }
 
         return super.setVisible(visible, restart);
@@ -348,21 +329,18 @@
 
     @Override
     public void setHotspot(int id, float x, float y) {
-        if (mTouchedRipples == null) {
-            mTouchedRipples = new SparseArray<Ripple>();
-            mActiveRipples = new Ripple[MAX_RIPPLES];
+        if (mRipples == null) {
+            mRipples = new SparseArray<Ripple>();
+            mAnimatingRipples = new Ripple[MAX_RIPPLES];
         }
 
-        if (mActiveRipplesCount >= MAX_RIPPLES) {
+        if (mAnimatingRipplesCount >= MAX_RIPPLES) {
             Log.e(LOG_TAG, "Max ripple count exceeded", new RuntimeException());
             return;
         }
 
-        final Ripple ripple = mTouchedRipples.get(id);
+        final Ripple ripple = mRipples.get(id);
         if (ripple == null) {
-            final Rect padding = mPaddingRect;
-            getPadding(padding);
-
             final Rect bounds = mHotspotBounds;
             if (mState.mPinned) {
                 x = bounds.exactCenterX();
@@ -371,11 +349,11 @@
 
             // TODO: Clean this up in the API.
             final boolean pulse = (id != R.attr.state_focused);
-            final Ripple newRipple = new Ripple(bounds, padding, x, y, mDensity, pulse);
-            newRipple.animate().enter();
+            final Ripple newRipple = new Ripple(this, bounds, mDensity, pulse);
+            newRipple.move(x, y);
 
-            mActiveRipples[mActiveRipplesCount++] = newRipple;
-            mTouchedRipples.put(id, newRipple);
+            mAnimatingRipples[mAnimatingRipplesCount++] = newRipple;
+            mRipples.put(id, newRipple);
         } else if (mState.mPinned) {
             final Rect bounds = mHotspotBounds;
             x = bounds.exactCenterX();
@@ -384,41 +362,37 @@
         } else {
             ripple.move(x, y);
         }
-
-        scheduleAnimation();
     }
 
     @Override
     public void removeHotspot(int id) {
-        if (mTouchedRipples == null) {
+        if (mRipples == null) {
             return;
         }
 
-        final Ripple ripple = mTouchedRipples.get(id);
+        final Ripple ripple = mRipples.get(id);
         if (ripple != null) {
-            ripple.animate().exit();
+            ripple.exit();
 
-            mTouchedRipples.remove(id);
-            scheduleAnimation();
+            mRipples.remove(id);
         }
     }
 
     @Override
     public void clearHotspots() {
-        if (mTouchedRipples == null) {
-            return;
+        if (mRipples != null) {
+            mRipples.clear();
         }
 
-        final int n = mTouchedRipples.size();
-        for (int i = 0; i < n; i++) {
-            // TODO: Use a fast exit, maybe just fade out?
-            mTouchedRipples.valueAt(i).animate().exit();
+        final int count = mAnimatingRipplesCount;
+        final Ripple[] ripples = mAnimatingRipples;
+        for (int i = 0; i < count; i++) {
+            ripples[i].cancel();
+            ripples[i] = null;
         }
 
-        if (n > 0) {
-            mTouchedRipples.clear();
-            scheduleAnimation();
-        }
+        mAnimatingRipplesCount = 0;
+        invalidateSelf();
     }
 
     /**
@@ -431,30 +405,6 @@
         onHotspotBoundsChange();
     }
 
-    /**
-     * Schedules the next animation, if necessary.
-     */
-    private void scheduleAnimation() {
-        if (mActiveRipplesCount == 0) {
-            mAnimating = false;
-        } else if (!mAnimating) {
-            mAnimating = true;
-
-            if (mAnimationRunnable == null) {
-                mAnimationRunnable = new Runnable() {
-                    @Override
-                    public void run() {
-                        mAnimating = false;
-                        scheduleAnimation();
-                        invalidateSelf();
-                    }
-                };
-            }
-
-            scheduleSelf(mAnimationRunnable, SystemClock.uptimeMillis() + 1000 / 60);
-        }
-    }
-
     @Override
     public void draw(Canvas canvas) {
         final int N = mLayerState.mNum;
@@ -501,12 +451,12 @@
     }
 
     private int drawRippleLayer(Canvas canvas, Rect bounds, boolean maskOnly) {
-        final int ripplesCount = mActiveRipplesCount;
-        if (ripplesCount == 0) {
+        final int count = mAnimatingRipplesCount;
+        if (count == 0) {
             return -1;
         }
 
-        final Ripple[] activeRipples = mActiveRipples;
+        final Ripple[] ripples = mAnimatingRipples;
         final boolean projected = isProjected();
         final Rect layerBounds = projected ? getDirtyBounds() : bounds;
 
@@ -529,17 +479,15 @@
 
         boolean drewRipples = false;
         int restoreToCount = -1;
-        int activeRipplesCount = 0;
+        int animatingCount = 0;
 
-        // Draw ripples.
-        for (int i = 0; i < ripplesCount; i++) {
-            final Ripple ripple = activeRipples[i];
-            final RippleAnimator animator = ripple.animate();
-            animator.update();
+        // Draw ripples and update the animating ripples array.
+        for (int i = 0; i < count; i++) {
+            final Ripple ripple = ripples[i];
 
-            // Mark and skip inactive ripples.
-            if (!animator.isRunning()) {
-                activeRipples[i] = null;
+            // Mark and skip finished ripples.
+            if (ripple.isFinished()) {
+                ripples[i] = null;
                 continue;
             }
 
@@ -565,11 +513,11 @@
 
             drewRipples |= ripple.draw(canvas, ripplePaint);
 
-            activeRipples[activeRipplesCount] = activeRipples[i];
-            activeRipplesCount++;
+            ripples[animatingCount] = ripples[i];
+            animatingCount++;
         }
 
-        mActiveRipplesCount = activeRipplesCount;
+        mAnimatingRipplesCount = animatingCount;
 
         // If we created a layer with no content, merge it immediately.
         if (restoreToCount >= 0 && !drewRipples) {
@@ -596,8 +544,8 @@
         drawingBounds.setEmpty();
 
         final Rect rippleBounds = mTempRect;
-        final Ripple[] activeRipples = mActiveRipples;
-        final int N = mActiveRipplesCount;
+        final Ripple[] activeRipples = mAnimatingRipples;
+        final int N = mAnimatingRipplesCount;
         for (int i = 0; i < N; i++) {
             activeRipples[i].getBounds(rippleBounds);
             drawingBounds.union(rippleBounds);
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index ee16586..6a3003e 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -20,130 +20,13 @@
 
 #include <set>
 
+#include "RenderNode.h"
 #include "RenderProperties.h"
 
 namespace android {
 namespace uirenderer {
 
 /************************************************************
- *  Private header
- ************************************************************/
-
-typedef void (RenderProperties::*SetFloatProperty)(float value);
-typedef float (RenderProperties::*GetFloatProperty)() const;
-
-struct PropertyAccessors {
-    GetFloatProperty getter;
-    SetFloatProperty setter;
-};
-
-// Maps RenderProperty enum to accessors
-static const PropertyAccessors PROPERTY_ACCESSOR_LUT[] = {
-    {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
-    {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
-    {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
-    {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
-    {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
-    {&RenderProperties::getRotation, &RenderProperties::setRotation },
-    {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
-    {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
-    {&RenderProperties::getX, &RenderProperties::setX },
-    {&RenderProperties::getY, &RenderProperties::setY },
-    {&RenderProperties::getZ, &RenderProperties::setZ },
-    {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
-};
-
-// Helper class to contain generic animator helpers
-class BaseAnimator {
-public:
-    BaseAnimator();
-    virtual ~BaseAnimator();
-
-    void setInterpolator(Interpolator* interpolator);
-    void setDuration(nsecs_t durationInMs);
-
-    bool isFinished() { return mPlayState == FINISHED; }
-
-protected:
-    // This is the main animation entrypoint that subclasses should call
-    // to generate the onAnimation* lifecycle events
-    // Returns true if the animation has finished, false otherwise
-    bool animateFrame(nsecs_t frameTime);
-
-    // Called when PlayState switches from PENDING to RUNNING
-    virtual void onAnimationStarted() {}
-    virtual void onAnimationUpdated(float fraction) = 0;
-    virtual void onAnimationFinished() {}
-
-private:
-    enum PlayState {
-        PENDING,
-        RUNNING,
-        FINISHED,
-    };
-
-    Interpolator* mInterpolator;
-    PlayState mPlayState;
-    long mStartTime;
-    long mDuration;
-};
-
-// Hide the base classes & private bits from the exported RenderPropertyAnimator
-// in this Impl class so that subclasses of RenderPropertyAnimator don't require
-// knowledge of the inner guts but only the public virtual methods.
-// Animates a single property
-class RenderPropertyAnimatorImpl : public BaseAnimator {
-public:
-    RenderPropertyAnimatorImpl(GetFloatProperty getter, SetFloatProperty setter,
-            RenderPropertyAnimator::DeltaValueType deltaType, float delta);
-    ~RenderPropertyAnimatorImpl();
-
-    bool animate(RenderProperties* target, TreeInfo& info);
-
-protected:
-    virtual void onAnimationStarted();
-    virtual void onAnimationUpdated(float fraction);
-
-private:
-    // mTarget is only valid inside animate()
-    RenderProperties* mTarget;
-    GetFloatProperty mGetter;
-    SetFloatProperty mSetter;
-
-    RenderPropertyAnimator::DeltaValueType mDeltaValueType;
-    float mDeltaValue;
-    float mFromValue;
-};
-
-RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
-        DeltaValueType deltaType, float deltaValue) {
-    PropertyAccessors pa = PROPERTY_ACCESSOR_LUT[property];
-    mImpl = new RenderPropertyAnimatorImpl(pa.getter, pa.setter, deltaType, deltaValue);
-}
-
-RenderPropertyAnimator::~RenderPropertyAnimator() {
-    delete mImpl;
-    mImpl = NULL;
-}
-
-void RenderPropertyAnimator::setInterpolator(Interpolator* interpolator) {
-    mImpl->setInterpolator(interpolator);
-}
-
-void RenderPropertyAnimator::setDuration(nsecs_t durationInMs) {
-    mImpl->setDuration(durationInMs);
-}
-
-bool RenderPropertyAnimator::isFinished() {
-    return mImpl->isFinished();
-}
-
-bool RenderPropertyAnimator::animate(RenderProperties* target, TreeInfo& info) {
-    return mImpl->animate(target, info);
-}
-
-
-/************************************************************
  *  Base animator
  ************************************************************/
 
@@ -168,10 +51,10 @@
     mDuration = duration;
 }
 
-bool BaseAnimator::animateFrame(nsecs_t frameTime) {
+bool BaseAnimator::animateFrame(TreeInfo& info) {
     if (mPlayState == PENDING) {
         mPlayState = RUNNING;
-        mStartTime = frameTime;
+        mStartTime = info.frameTimeMs;
         // No interpolator was set, use the default
         if (!mInterpolator) {
             setInterpolator(Interpolator::createDefaultInterpolator());
@@ -181,7 +64,7 @@
 
     float fraction = 1.0f;
     if (mPlayState == RUNNING) {
-        fraction = mDuration > 0 ? (float)(frameTime - mStartTime) / mDuration : 1.0f;
+        fraction = mDuration > 0 ? (float)(info.frameTimeMs - mStartTime) / mDuration : 1.0f;
         if (fraction >= 1.0f) {
             fraction = 1.0f;
             mPlayState = FINISHED;
@@ -192,48 +75,140 @@
 
     if (mPlayState == FINISHED) {
         onAnimationFinished();
+        callOnFinishedListener(info);
         return true;
     }
     return false;
 }
 
+void BaseAnimator::callOnFinishedListener(TreeInfo& info) {
+    if (mListener.get()) {
+        if (!info.animationHook) {
+            mListener->onAnimationFinished(this);
+        } else {
+            info.animationHook->callOnFinished(this, mListener.get());
+        }
+    }
+}
+
+/************************************************************
+ *  BaseRenderNodeAnimator
+ ************************************************************/
+
+BaseRenderNodeAnimator::BaseRenderNodeAnimator(
+                BaseRenderNodeAnimator::DeltaValueType deltaType, float delta)
+        : mTarget(0)
+        , mDeltaValueType(deltaType)
+        , mDeltaValue(delta)
+        , mFromValue(-1) {
+}
+
+bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
+    mTarget = target;
+    bool finished = animateFrame(info);
+    mTarget = NULL;
+    return finished;
+}
+
+void BaseRenderNodeAnimator::onAnimationStarted() {
+    mFromValue = getValue();
+
+    if (mDeltaValueType == BaseRenderNodeAnimator::ABSOLUTE) {
+        mDeltaValue = (mDeltaValue - mFromValue);
+        mDeltaValueType = BaseRenderNodeAnimator::DELTA;
+    }
+}
+
+void BaseRenderNodeAnimator::onAnimationUpdated(float fraction) {
+    float value = mFromValue + (mDeltaValue * fraction);
+    setValue(value);
+}
+
 /************************************************************
  *  RenderPropertyAnimator
  ************************************************************/
 
-RenderPropertyAnimatorImpl::RenderPropertyAnimatorImpl(
-                GetFloatProperty getter, SetFloatProperty setter,
-                RenderPropertyAnimator::DeltaValueType deltaType, float delta)
-        : mTarget(0)
-        , mGetter(getter)
-        , mSetter(setter)
-        , mDeltaValueType(deltaType)
-        , mDeltaValue(delta)
-        , mFromValue(-1) {
+// Maps RenderProperty enum to accessors
+const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
+    {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
+    {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
+    {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
+    {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
+    {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
+    {&RenderProperties::getRotation, &RenderProperties::setRotation },
+    {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
+    {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
+    {&RenderProperties::getX, &RenderProperties::setX },
+    {&RenderProperties::getY, &RenderProperties::setY },
+    {&RenderProperties::getZ, &RenderProperties::setZ },
+    {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
+};
+
+RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
+                DeltaValueType deltaType, float deltaValue)
+        : BaseRenderNodeAnimator(deltaType, deltaValue)
+        , mPropertyAccess(PROPERTY_ACCESSOR_LUT[property]) {
 }
 
-RenderPropertyAnimatorImpl::~RenderPropertyAnimatorImpl() {
+float RenderPropertyAnimator::getValue() const {
+    return (target()->animatorProperties().*mPropertyAccess.getter)();
 }
 
-bool RenderPropertyAnimatorImpl::animate(RenderProperties* target, TreeInfo& info) {
-    mTarget = target;
-    bool finished = animateFrame(info.frameTimeMs);
-    mTarget = NULL;
-    return finished;
+void RenderPropertyAnimator::setValue(float value) {
+    (target()->animatorProperties().*mPropertyAccess.setter)(value);
 }
 
-void RenderPropertyAnimatorImpl::onAnimationStarted() {
-    mFromValue = (mTarget->*mGetter)();
+/************************************************************
+ *  CanvasPropertyPrimitiveAnimator
+ ************************************************************/
 
-    if (mDeltaValueType == RenderPropertyAnimator::ABSOLUTE) {
-        mDeltaValue = (mDeltaValue - mFromValue);
-        mDeltaValueType = RenderPropertyAnimator::DELTA;
+CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
+                CanvasPropertyPrimitive* property, DeltaValueType deltaType, float deltaValue)
+        : BaseRenderNodeAnimator(deltaType, deltaValue)
+        , mProperty(property) {
+}
+
+float CanvasPropertyPrimitiveAnimator::getValue() const {
+    return mProperty->value;
+}
+
+void CanvasPropertyPrimitiveAnimator::setValue(float value) {
+    mProperty->value = value;
+}
+
+/************************************************************
+ *  CanvasPropertySkPaintAnimator
+ ************************************************************/
+
+CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
+                CanvasPropertyPaint* property, PaintField field,
+                DeltaValueType deltaType, float deltaValue)
+        : BaseRenderNodeAnimator(deltaType, deltaValue)
+        , mProperty(property)
+        , mField(field) {
+}
+
+float CanvasPropertyPaintAnimator::getValue() const {
+    switch (mField) {
+    case STROKE_WIDTH:
+        return mProperty->value.getStrokeWidth();
+    case ALPHA:
+        return mProperty->value.getAlpha();
     }
+    LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
+    return -1;
 }
 
-void RenderPropertyAnimatorImpl::onAnimationUpdated(float fraction) {
-    float value = mFromValue + (mDeltaValue * fraction);
-    (mTarget->*mSetter)(value);
+void CanvasPropertyPaintAnimator::setValue(float value) {
+    switch (mField) {
+    case STROKE_WIDTH:
+        mProperty->value.setStrokeWidth(value);
+        return;
+    case ALPHA:
+        mProperty->value.setAlpha(value);
+        return;
+    }
+    LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
 }
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 1c8361b..0b074cc 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -17,18 +17,72 @@
 #define ANIMATOR_H
 
 #include <cutils/compiler.h>
+#include <utils/StrongPointer.h>
 
+#include "CanvasProperty.h"
 #include "Interpolator.h"
 #include "TreeInfo.h"
+#include "utils/Macros.h"
 #include "utils/VirtualLightRefBase.h"
 
 namespace android {
 namespace uirenderer {
 
+class RenderNode;
 class RenderProperties;
-class RenderPropertyAnimatorImpl;
 
-class RenderPropertyAnimator : public VirtualLightRefBase {
+class AnimationListener : public VirtualLightRefBase {
+public:
+    ANDROID_API virtual void onAnimationFinished(BaseAnimator*) = 0;
+protected:
+    ANDROID_API virtual ~AnimationListener() {}
+};
+
+// Helper class to contain generic animator helpers
+class BaseAnimator : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(BaseAnimator);
+public:
+
+    ANDROID_API void setInterpolator(Interpolator* interpolator);
+    ANDROID_API void setDuration(nsecs_t durationInMs);
+    ANDROID_API void setListener(AnimationListener* listener) {
+        mListener = listener;
+    }
+
+    bool isFinished() { return mPlayState == FINISHED; }
+
+protected:
+    BaseAnimator();
+    virtual ~BaseAnimator();
+
+    // This is the main animation entrypoint that subclasses should call
+    // to generate the onAnimation* lifecycle events
+    // Returns true if the animation has finished, false otherwise
+    bool animateFrame(TreeInfo& info);
+
+    // Called when PlayState switches from PENDING to RUNNING
+    virtual void onAnimationStarted() {}
+    virtual void onAnimationUpdated(float fraction) = 0;
+    virtual void onAnimationFinished() {}
+
+private:
+    void callOnFinishedListener(TreeInfo& info);
+
+    enum PlayState {
+        PENDING,
+        RUNNING,
+        FINISHED,
+    };
+
+    Interpolator* mInterpolator;
+    PlayState mPlayState;
+    long mStartTime;
+    long mDuration;
+
+   sp<AnimationListener> mListener;
+};
+
+class BaseRenderNodeAnimator : public BaseAnimator {
 public:
     // Since the UI thread doesn't necessarily know what the current values
     // actually are and thus can't do the calculations, this is used to inform
@@ -43,6 +97,29 @@
         DELTA,
     };
 
+    bool animate(RenderNode* target, TreeInfo& info);
+
+protected:
+    BaseRenderNodeAnimator(DeltaValueType deltaType, float deltaValue);
+
+    RenderNode* target() const { return mTarget; }
+    virtual float getValue() const = 0;
+    virtual void setValue(float value) = 0;
+
+private:
+    virtual void onAnimationStarted();
+    virtual void onAnimationUpdated(float fraction);
+
+    // mTarget is only valid inside animate()
+    RenderNode* mTarget;
+
+    BaseRenderNodeAnimator::DeltaValueType mDeltaValueType;
+    float mDeltaValue;
+    float mFromValue;
+};
+
+class RenderPropertyAnimator : public BaseRenderNodeAnimator {
+public:
     enum RenderProperty {
         TRANSLATION_X = 0,
         TRANSLATION_Y,
@@ -58,19 +135,53 @@
         ALPHA,
     };
 
-    ANDROID_API void setInterpolator(Interpolator* interpolator);
-    ANDROID_API void setDuration(nsecs_t durationInMs);
-    ANDROID_API bool isFinished();
-
-    bool animate(RenderProperties* target, TreeInfo& info);
+    ANDROID_API RenderPropertyAnimator(RenderProperty property,
+                DeltaValueType deltaType, float deltaValue);
 
 protected:
-    ANDROID_API RenderPropertyAnimator(RenderProperty property, DeltaValueType deltaType,
-            float deltaValue);
-    ANDROID_API virtual ~RenderPropertyAnimator();
+    ANDROID_API virtual float getValue() const;
+    ANDROID_API virtual void setValue(float value);
 
 private:
-    RenderPropertyAnimatorImpl* mImpl;
+    typedef void (RenderProperties::*SetFloatProperty)(float value);
+    typedef float (RenderProperties::*GetFloatProperty)() const;
+
+    struct PropertyAccessors {
+        GetFloatProperty getter;
+        SetFloatProperty setter;
+    };
+
+    PropertyAccessors mPropertyAccess;
+
+    static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
+};
+
+class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
+public:
+    ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
+            DeltaValueType deltaType, float deltaValue);
+protected:
+    ANDROID_API virtual float getValue() const;
+    ANDROID_API virtual void setValue(float value);
+private:
+    sp<CanvasPropertyPrimitive> mProperty;
+};
+
+class CanvasPropertyPaintAnimator : public BaseRenderNodeAnimator {
+public:
+    enum PaintField {
+        STROKE_WIDTH = 0,
+        ALPHA,
+    };
+
+    ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
+            PaintField field, DeltaValueType deltaType, float deltaValue);
+protected:
+    ANDROID_API virtual float getValue() const;
+    ANDROID_API virtual void setValue(float value);
+private:
+    sp<CanvasPropertyPaint> mProperty;
+    PaintField mField;
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index df2123b..43223ec 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -691,9 +691,10 @@
     propertyAmbientShadowStrength = 25;
     propertySpotShadowStrength = 25;
 
-    propertyLightPosXScale = 0.5f;
-    propertyLightPosYScale = 0.0f;
-    propertyLightPosZScale = 1.0f;
+    propertyLightDiameter = -1.0f;
+    propertyLightPosY = -1.0f;
+    propertyLightPosZ = -1.0f;
+    propertyAmbientRatio = -1.0f;
 }
 
 void Caches::setTempProperty(const char* name, const char* value) {
@@ -706,17 +707,21 @@
         propertySpotShadowStrength = atoi(value);
         ALOGD("spot shadow strength = 0x%x out of 0xff", propertySpotShadowStrength);
         return;
-    } else if (!strcmp(name, "lightPosXScale")) {
-        propertyLightPosXScale = fmin(fmax(atof(value), 0.0), 1.0);
-        ALOGD("lightPos X Scale = %.2f", propertyLightPosXScale);
+    } else if (!strcmp(name, "ambientRatio")) {
+        propertyAmbientRatio = fmin(fmax(atof(value), 0.0), 10.0);
+        ALOGD("ambientRatio = %.2f", propertyAmbientRatio);
         return;
-    }  else if (!strcmp(name, "lightPosYScale")) {
-        propertyLightPosYScale = fmin(fmax(atof(value), 0.0), 1.0);
-        ALOGD("lightPos Y Scale = %.2f", propertyLightPosXScale);
+    } else if (!strcmp(name, "lightDiameter")) {
+        propertyLightDiameter = fmin(fmax(atof(value), 0.0), 3000.0);
+        ALOGD("lightDiameter = %.2f", propertyLightDiameter);
         return;
-    }  else if (!strcmp(name, "lightPosZScale")) {
-        propertyLightPosZScale = fmin(fmax(atof(value), 0.0), 1.0);
-        ALOGD("lightPos Z Scale = %.2f", propertyLightPosXScale);
+    }  else if (!strcmp(name, "lightPosY")) {
+        propertyLightPosY = fmin(fmax(atof(value), 0.0), 3000.0);
+        ALOGD("lightPos Y = %.2f", propertyLightPosY);
+        return;
+    }  else if (!strcmp(name, "lightPosZ")) {
+        propertyLightPosZ = fmin(fmax(atof(value), 0.0), 3000.0);
+        ALOGD("lightPos Z = %.2f", propertyLightPosZ);
         return;
     }
     ALOGD("    failed");
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index ba3ccaf..2e2ee15 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -352,13 +352,10 @@
     void initTempProperties();
     void setTempProperty(const char* name, const char* value);
 
-    // These scaling factors range from 0 to 1, to scale the light position
-    // within the bound of (screenwidth, screenheight, max(screenwidth, screenheight));
-    // The default scale is (0.5, 0, 1) which put the light at
-    // (screenwidth / 2, 0, max(screenwidth, screenheight)).
-    float propertyLightPosXScale;
-    float propertyLightPosYScale;
-    float propertyLightPosZScale;
+    float propertyLightDiameter;
+    float propertyLightPosY;
+    float propertyLightPosZ;
+    float propertyAmbientRatio;
     int propertyAmbientShadowStrength;
     int propertySpotShadowStrength;
 
diff --git a/libs/hwui/CanvasProperty.h b/libs/hwui/CanvasProperty.h
new file mode 100644
index 0000000..2e1d176
--- /dev/null
+++ b/libs/hwui/CanvasProperty.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef CANVASPROPERTY_H
+#define CANVASPROPERTY_H
+
+#include "utils/Macros.h"
+#include "utils/VirtualLightRefBase.h"
+
+#include <SkPaint.h>
+
+namespace android {
+namespace uirenderer {
+
+class CanvasPropertyPrimitive : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(CanvasPropertyPrimitive);
+public:
+    CanvasPropertyPrimitive(float initialValue) : value(initialValue) {}
+
+    float value;
+};
+
+class CanvasPropertyPaint : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(CanvasPropertyPaint);
+public:
+    CanvasPropertyPaint(const SkPaint& initialValue) : value(initialValue) {}
+
+    SkPaint value;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* CANVASPROPERTY_H */
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index fe70d13..eaeb772 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -140,6 +140,14 @@
     void addChild(DrawDisplayListOp* childOp);
     const Vector<DrawDisplayListOp*>& children() { return mChildren; }
 
+    void refProperty(CanvasPropertyPrimitive* prop) {
+        mReferenceHolders.push(prop);
+    }
+
+    void refProperty(CanvasPropertyPaint* prop) {
+        mReferenceHolders.push(prop);
+    }
+
 private:
     Vector< sp<VirtualLightRefBase> > mReferenceHolders;
 
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 6dfb918..ce92beb 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1198,6 +1198,27 @@
     float mRadius;
 };
 
+class DrawCirclePropsOp : public DrawOp {
+public:
+    DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
+            : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
+
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
+        return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
+    }
+
+    virtual void output(int level, uint32_t logFlags) const {
+        OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
+    }
+
+    virtual const char* name() { return "DrawCircleProps"; }
+
+private:
+    float* mX;
+    float* mY;
+    float* mRadius;
+};
+
 class DrawOvalOp : public DrawStrokableOp {
 public:
     DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index e36d975..8afd106 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -299,6 +299,17 @@
     return DrawGlInfo::kStatusDone;
 }
 
+status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+        CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+    mDisplayListData->refProperty(x);
+    mDisplayListData->refProperty(y);
+    mDisplayListData->refProperty(radius);
+    mDisplayListData->refProperty(paint);
+    addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
+            &radius->value, &paint->value));
+    return DrawGlInfo::kStatusDone;
+}
+
 status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
         const SkPaint* paint) {
     paint = refPaint(paint);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 04c5a73..25e78c1 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -135,6 +135,8 @@
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint* paint);
     virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+    virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+                CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
     virtual status_t drawOval(float left, float top, float right, float bottom,
             const SkPaint* paint);
     virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 4569152..95fdb04 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -3291,10 +3291,8 @@
     if (mCaches.propertySpotShadowStrength > 0) {
         paint.setARGB(casterAlpha * mCaches.propertySpotShadowStrength, 0, 0, 0);
         VertexBuffer spotShadowVertexBuffer;
-        Vector3 lightPosScale(mCaches.propertyLightPosXScale,
-                mCaches.propertyLightPosYScale, mCaches.propertyLightPosZScale);
         VertexBufferMode vertexBufferMode = ShadowTessellator::tessellateSpotShadow(
-                isCasterOpaque, casterPolygon, casterVertexCount, lightPosScale,
+                isCasterOpaque, casterPolygon, casterVertexCount,
                 *currentTransform(), getWidth(), getHeight(), casterBounds, localClip,
                 spotShadowVertexBuffer);
         drawVertexBuffer(vertexBufferMode, spotShadowVertexBuffer, &paint);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b49d1e1..7794abc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -49,6 +49,7 @@
 #include "UvMapper.h"
 #include "Vertex.h"
 #include "Caches.h"
+#include "CanvasProperty.h"
 
 namespace android {
 namespace uirenderer {
@@ -200,6 +201,12 @@
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint* paint);
     virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+    virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+            CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+        // TODO: Remove once android_view_GLES20Canvas uses DisplayListRenderer
+        // directly
+        return drawCircle(x->value, y->value, radius->value, &paint->value);
+    }
     virtual status_t drawOval(float left, float top, float right, float bottom,
             const SkPaint* paint);
     virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index dcd6bda..2c29985 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -109,7 +109,7 @@
     prepareSubTree(info, mDisplayListData);
 }
 
-static bool is_finished(const sp<RenderPropertyAnimator>& animator) {
+static bool is_finished(const sp<BaseRenderNodeAnimator>& animator) {
     return animator->isFinished();
 }
 
@@ -119,8 +119,8 @@
         mProperties = mStagingProperties;
     }
     if (mNeedsAnimatorsSync) {
-        mAnimators.reserve(mStagingAnimators.size());
-        std::vector< sp<RenderPropertyAnimator> >::iterator it;
+        mAnimators.resize(mStagingAnimators.size());
+        std::vector< sp<BaseRenderNodeAnimator> >::iterator it;
         // hint: this means copy_if_not()
         it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
                 mAnimators.begin(), is_finished);
@@ -141,26 +141,22 @@
 
 class AnimateFunctor {
 public:
-    AnimateFunctor(RenderProperties* target, TreeInfo& info)
+    AnimateFunctor(RenderNode* target, TreeInfo& info)
             : mTarget(target), mInfo(info) {}
 
-    bool operator() (sp<RenderPropertyAnimator>& animator) {
-        bool finished = animator->animate(mTarget, mInfo);
-        if (finished && mInfo.animationListener) {
-            mInfo.animationListener->onAnimationFinished(animator);
-        }
-        return finished;
+    bool operator() (sp<BaseRenderNodeAnimator>& animator) {
+        return animator->animate(mTarget, mInfo);
     }
 private:
-    RenderProperties* mTarget;
+    RenderNode* mTarget;
     TreeInfo& mInfo;
 };
 
 void RenderNode::evaluateAnimations(TreeInfo& info) {
     if (!mAnimators.size()) return;
 
-    AnimateFunctor functor(&mProperties, info);
-    std::vector< sp<RenderPropertyAnimator> >::iterator newEnd;
+    AnimateFunctor functor(this, info);
+    std::vector< sp<BaseRenderNodeAnimator> >::iterator newEnd;
     newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
     mAnimators.erase(newEnd, mAnimators.end());
     mProperties.updateMatrix();
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 294f436..159903c 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -128,6 +128,10 @@
         return mProperties;
     }
 
+    RenderProperties& animatorProperties() {
+        return mProperties;
+    }
+
     const RenderProperties& stagingProperties() {
         return mStagingProperties;
     }
@@ -148,13 +152,13 @@
     ANDROID_API virtual void prepareTree(TreeInfo& info);
 
     // UI thread only!
-    ANDROID_API void addAnimator(const sp<RenderPropertyAnimator>& animator) {
+    ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
         mStagingAnimators.insert(animator);
         mNeedsAnimatorsSync = true;
     }
 
     // UI thread only!
-    ANDROID_API void removeAnimator(const sp<RenderPropertyAnimator>& animator) {
+    ANDROID_API void removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
         mStagingAnimators.erase(animator);
         mNeedsAnimatorsSync = true;
     }
@@ -233,8 +237,8 @@
     DisplayListData* mStagingDisplayListData;
 
     bool mNeedsAnimatorsSync;
-    std::set< sp<RenderPropertyAnimator> > mStagingAnimators;
-    std::vector< sp<RenderPropertyAnimator> > mAnimators;
+    std::set< sp<BaseRenderNodeAnimator> > mStagingAnimators;
+    std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
 
     /**
      * Draw time state - these properties are only set and used during rendering
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index ee60a63..be49aed 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -22,6 +22,7 @@
 #include <utils/Trace.h>
 
 #include "AmbientShadow.h"
+#include "Caches.h"
 #include "ShadowTessellator.h"
 #include "SpotShadow.h"
 
@@ -41,9 +42,14 @@
 
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
-    const float heightFactor = 1.0f / 128;
+    float heightFactor = 1.0f / 128;
     const float geomFactor = 64;
 
+    Caches& caches = Caches::getInstance();
+    if (CC_UNLIKELY(caches.propertyAmbientRatio > 0.0f)) {
+        heightFactor *= caches.propertyAmbientRatio;
+    }
+
     Rect ambientShadowBounds(casterBounds);
     ambientShadowBounds.outset(maxZ * geomFactor * heightFactor);
 
@@ -62,16 +68,26 @@
 
 VertexBufferMode ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque,
         const Vector3* casterPolygon, int casterVertexCount,
-        const Vector3& lightPosScale, const mat4& receiverTransform,
+        const mat4& receiverTransform,
         int screenWidth, int screenHeight, const Rect& casterBounds,
         const Rect& localClip, VertexBuffer& shadowVertexBuffer) {
     ATRACE_CALL();
 
+    Caches& caches = Caches::getInstance();
+
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
     int maximal = max(screenWidth, screenHeight);
-    Vector3 lightCenter(screenWidth * lightPosScale.x, screenHeight * lightPosScale.y,
-            maximal * lightPosScale.z);
+    Vector3 lightCenter(screenWidth * 0.5f, 0, maximal);
+
+    if (CC_UNLIKELY(caches.propertyLightPosY > 0)) {
+        lightCenter.y = - caches.propertyLightPosY; // negated since this shifts up
+    }
+    if (CC_UNLIKELY(caches.propertyLightPosZ > 0)) {
+        lightCenter.z = caches.propertyLightPosZ;
+    }
+
+
 #if DEBUG_SHADOW
     ALOGD("light center %f %f %f", lightCenter.x, lightCenter.y, lightCenter.z);
 #endif
@@ -82,9 +98,13 @@
     reverseReceiverTransform.loadInverse(receiverTransform);
     reverseReceiverTransform.mapPoint3d(lightCenter);
 
-    const float lightSize = maximal / 4;
+    float lightSize = maximal / 4;
     const int lightVertexCount = 8;
 
+    if (CC_UNLIKELY(caches.propertyLightDiameter > 0)) {
+        lightSize = caches.propertyLightDiameter;
+    }
+
     // Now light and caster are both in local space, we will check whether
     // the shadow is within the clip area.
     Rect lightRect = Rect(lightCenter.x - lightSize, lightCenter.y - lightSize,
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index 64e69bc..e5a3da1 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -73,7 +73,7 @@
 
     static VertexBufferMode tessellateSpotShadow(bool isCasterOpaque,
             const Vector3* casterPolygon, int casterVertexCount,
-            const Vector3& lightPosScale, const mat4& receiverTransform,
+            const mat4& receiverTransform,
             int screenWidth, int screenHeight, const Rect& casterBounds,
             const Rect& localClip, VertexBuffer& shadowVertexBuffer);
 
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 8957607..a383fbf 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -16,20 +16,19 @@
 #ifndef TREEINFO_H
 #define TREEINFO_H
 
-#include <cutils/compiler.h>
 #include <utils/Timers.h>
-#include <utils/StrongPointer.h>
 
 namespace android {
 namespace uirenderer {
 
-class RenderPropertyAnimator;
+class BaseAnimator;
+class AnimationListener;
 
-class AnimationListener {
+class AnimationHook {
 public:
-    ANDROID_API virtual void onAnimationFinished(const sp<RenderPropertyAnimator>&) = 0;
+    virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) = 0;
 protected:
-    ANDROID_API virtual ~AnimationListener() {}
+    ~AnimationHook() {}
 };
 
 struct TreeInfo {
@@ -41,7 +40,7 @@
             , frameTimeMs(0)
             , evaluateAnimations(false)
             , hasAnimations(false)
-            , animationListener(0)
+            , animationHook(0)
     {}
 
     bool hasFunctors;
@@ -53,7 +52,7 @@
     bool evaluateAnimations;
     // This is only updated if evaluateAnimations is true
     bool hasAnimations;
-    AnimationListener* animationListener;
+    AnimationHook* animationHook;
 
     // TODO: Damage calculations
 };
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index ff4be71..45f5cb0 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -112,6 +112,10 @@
     initTreeInfo(info);
     mContext->processLayerUpdates(&mLayers, info);
     mContext->prepareTree(info);
+    if (info.hasAnimations) {
+        // TODO: dirty calculations, for now just do a full-screen inval
+        mDirty.setEmpty();
+    }
     // If prepareTextures is false, we ran out of texture cache space
     return !info.hasFunctors && info.prepareTextures;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/libs/hwui/utils/Macros.h
similarity index 69%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
rename to libs/hwui/utils/Macros.h
index 0377123..14a3ec0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/libs/hwui/utils/Macros.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,11 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#ifndef MACROS_H
+#define MACROS_H
 
-package com.android.systemui.statusbar.policy;
+#define PREVENT_COPY_AND_ASSIGN(Type) \
+    private: \
+        Type(const Type&); \
+        void operator=(const Type&)
 
-import android.view.View;
 
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+#endif /* MACROS_H */
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 8ae06e0..1dcfcb8 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.media.RemoteController.OnClientUpdateListener;
+import android.media.session.MediaSessionLegacyHelper;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -48,6 +49,12 @@
  */
 public class AudioManager {
 
+    // If we should use the new sessions APIs.
+    private final static boolean USE_SESSIONS = true;
+    // If we should use the legacy APIs. If both are true information will be
+    // duplicated through both paths. Currently this flag isn't used.
+    private final static boolean USE_LEGACY = true;
+
     private final Context mContext;
     private long mVolumeKeyUpTime;
     private final boolean mUseMasterVolume;
@@ -421,6 +428,7 @@
     public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE;
 
     private static IAudioService sService;
+    private MediaSessionLegacyHelper mSessionHelper;
 
     /**
      * @hide
@@ -431,6 +439,9 @@
                 com.android.internal.R.bool.config_useMasterVolume);
         mUseVolumeKeySounds = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_useVolumeKeySounds);
+        if (USE_SESSIONS) {
+            mSessionHelper = MediaSessionLegacyHelper.getHelper(context);
+        }
     }
 
     private static IAudioService getService()
@@ -2166,6 +2177,9 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in registerMediaButtonIntent"+e);
         }
+        if (USE_SESSIONS) {
+            mSessionHelper.addMediaButtonListener(pi, mContext);
+        }
     }
 
     /**
@@ -2239,6 +2253,9 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in unregisterMediaButtonIntent"+e);
         }
+        if (USE_SESSIONS) {
+            mSessionHelper.removeMediaButtonListener(pi);
+        }
     }
 
     /**
@@ -2263,6 +2280,9 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in registerRemoteControlClient"+e);
         }
+        if (USE_SESSIONS) {
+            rcClient.registerWithSession(mSessionHelper);
+        }
     }
 
     /**
@@ -2282,6 +2302,9 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in unregisterRemoteControlClient"+e);
         }
+        if (USE_SESSIONS) {
+            rcClient.unregisterWithSession(mSessionHelper);
+        }
     }
 
     /**
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 4513ead..0c8a823 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -1787,6 +1787,11 @@
 
     /** @see AudioManager#playSoundEffect(int, float) */
     public void playSoundEffectVolume(int effectType, float volume) {
+        if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
+            Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
+            return;
+        }
+
         sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
                 effectType, (int) (volume * 1000), null, 0);
     }
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index 2dea509..1c73c05 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -1250,8 +1250,6 @@
                 }
                 if (prse.hasMatchingMediaButtonIntent(mediaIntent)) {
                     inStackIndex = index;
-                    // found it, ok to stop here
-                    break;
                 }
             }
 
@@ -1272,7 +1270,11 @@
                         mPRStack.push(prse);
                     } else {
                         // and put it after the ones with active playback
-                        mPRStack.add(lastPlayingIndex, prse);
+                        if (inStackIndex > lastPlayingIndex) {
+                            mPRStack.add(lastPlayingIndex, prse);
+                        } else {
+                            mPRStack.add(lastPlayingIndex - 1, prse);
+                        }
                     }
                 }
             }
@@ -2151,13 +2153,13 @@
                 // of this RemoteControlClient (note that it may not be in the stack)
                 for (int index = mPRStack.size()-1; index >= 0; index--) {
                     prse = mPRStack.elementAt(index);
-                    if (prse.isPlaybackActive()) {
-                        lastPlayingIndex = index;
-                    }
                     if (prse.getRccId() == rccId) {
                         inStackIndex = index;
                         prse.mPlaybackState = newState;
                     }
+                    if (prse.isPlaybackActive()) {
+                        lastPlayingIndex = index;
+                    }
                 }
 
                 if (inStackIndex != -1) {
@@ -2177,7 +2179,11 @@
                             mPRStack.push(prse);
                         } else {
                             // and put it after the ones with active playback
-                            mPRStack.add(lastPlayingIndex, prse);
+                            if (inStackIndex > lastPlayingIndex) {
+                                mPRStack.add(lastPlayingIndex, prse);
+                            } else {
+                                mPRStack.add(lastPlayingIndex - 1, prse);
+                            }
                         }
                     }
 
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index eb91668..d3b1520 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -28,9 +28,12 @@
 import java.net.URL;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
+import java.net.NoRouteToHostException;
 import java.util.HashMap;
 import java.util.Map;
 
+import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
+
 /** @hide */
 public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
     private static final String TAG = "MediaHTTPConnection";
@@ -43,6 +46,12 @@
     private long mTotalSize = -1;
     private InputStream mInputStream = null;
 
+    private boolean mAllowCrossDomainRedirect = true;
+
+    // from com.squareup.okhttp.internal.http
+    private final static int HTTP_TEMP_REDIRECT = 307;
+    private final static int MAX_REDIRECTS = 20;
+
     public MediaHTTPConnection() {
         if (CookieHandler.getDefault() == null) {
             CookieHandler.setDefault(new CookieManager());
@@ -59,6 +68,7 @@
 
         try {
             disconnect();
+            mAllowCrossDomainRedirect = true;
             mURL = new URL(uri);
             mHeaders = convertHeaderStringToMap(headers);
         } catch (MalformedURLException e) {
@@ -68,6 +78,25 @@
         return native_getIMemory();
     }
 
+    private boolean parseBoolean(String val) {
+        try {
+            return Long.parseLong(val) != 0;
+        } catch (NumberFormatException e) {
+            return "true".equalsIgnoreCase(val) ||
+                "yes".equalsIgnoreCase(val);
+        }
+    }
+
+    /* returns true iff header is internal */
+    private boolean filterOutInternalHeaders(String key, String val) {
+        if ("android-allow-cross-domain-redirect".equalsIgnoreCase(key)) {
+            mAllowCrossDomainRedirect = parseBoolean(val);
+        } else {
+            return false;
+        }
+        return true;
+    }
+
     private Map<String, String> convertHeaderStringToMap(String headers) {
         HashMap<String, String> map = new HashMap<String, String>();
 
@@ -78,7 +107,9 @@
                 String key = pair.substring(0, colonPos);
                 String val = pair.substring(colonPos + 1);
 
-                map.put(key, val);
+                if (!filterOutInternalHeaders(key, val)) {
+                    map.put(key, val);
+                }
             }
         }
 
@@ -107,24 +138,75 @@
         teardownConnection();
 
         try {
-            mConnection = (HttpURLConnection)mURL.openConnection();
+            int response;
+            int redirectCount = 0;
 
-            if (mHeaders != null) {
-                for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
+            URL url = mURL;
+            while (true) {
+                mConnection = (HttpURLConnection)url.openConnection();
+                // handle redirects ourselves if we do not allow cross-domain redirect
+                mConnection.setInstanceFollowRedirects(mAllowCrossDomainRedirect);
+
+                if (mHeaders != null) {
+                    for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
+                        mConnection.setRequestProperty(
+                                entry.getKey(), entry.getValue());
+                    }
+                }
+
+                if (offset > 0) {
                     mConnection.setRequestProperty(
-                            entry.getKey(), entry.getValue());
+                            "Range", "bytes=" + offset + "-");
+                }
+
+                response = mConnection.getResponseCode();
+                if (response != HttpURLConnection.HTTP_MULT_CHOICE &&
+                        response != HttpURLConnection.HTTP_MOVED_PERM &&
+                        response != HttpURLConnection.HTTP_MOVED_TEMP &&
+                        response != HttpURLConnection.HTTP_SEE_OTHER &&
+                        response != HTTP_TEMP_REDIRECT) {
+                    // not a redirect, or redirect handled by HttpURLConnection
+                    break;
+                }
+
+                if (++redirectCount > MAX_REDIRECTS) {
+                    throw new NoRouteToHostException("Too many redirects: " + redirectCount);
+                }
+
+                String method = mConnection.getRequestMethod();
+                if (response == HTTP_TEMP_REDIRECT &&
+                        !method.equals("GET") && !method.equals("HEAD")) {
+                    // "If the 307 status code is received in response to a
+                    // request other than GET or HEAD, the user agent MUST NOT
+                    // automatically redirect the request"
+                    throw new NoRouteToHostException("Invalid redirect");
+                }
+                String location = mConnection.getHeaderField("Location");
+                if (location == null) {
+                    throw new NoRouteToHostException("Invalid redirect");
+                }
+                url = new URL(mURL /* TRICKY: don't use url! */, location);
+                if (!url.getProtocol().equals("https") &&
+                        !url.getProtocol().equals("http")) {
+                    throw new NoRouteToHostException("Unsupported protocol redirect");
+                }
+                boolean sameHost = mURL.getHost().equals(url.getHost());
+                if (!sameHost) {
+                    throw new NoRouteToHostException("Cross-domain redirects are disallowed");
+                }
+
+                if (response != HTTP_TEMP_REDIRECT) {
+                    // update effective URL, unless it is a Temporary Redirect
+                    mURL = url;
                 }
             }
 
-            if (offset > 0) {
-                mConnection.setRequestProperty(
-                        "Range", "bytes=" + offset + "-");
+            if (mAllowCrossDomainRedirect) {
+                // remember the current, potentially redirected URL if redirects
+                // were handled by HttpURLConnection
+                mURL = mConnection.getURL();
             }
 
-            int response = mConnection.getResponseCode();
-            // remember the current, possibly redirected URL
-            mURL = mConnection.getURL();
-
             if (response == HttpURLConnection.HTTP_PARTIAL) {
                 // Partial content, we cannot just use getContentLength
                 // because what we want is not just the length of the range
@@ -207,6 +289,9 @@
             }
 
             return n;
+        } catch (NoRouteToHostException e) {
+            Log.w(TAG, "readAt " + offset + " / " + size + " => " + e);
+            return MEDIA_ERROR_UNSUPPORTED;
         } catch (IOException e) {
             if (VERBOSE) {
                 Log.d(TAG, "readAt " + offset + " / " + size + " => -1");
diff --git a/media/java/android/media/MediaMetadataEditor.java b/media/java/android/media/MediaMetadataEditor.java
index 3bfdb5a..1a4e8da 100644
--- a/media/java/android/media/MediaMetadataEditor.java
+++ b/media/java/android/media/MediaMetadataEditor.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.graphics.Bitmap;
+import android.media.session.MediaMetadata;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.util.Log;
@@ -106,6 +107,10 @@
      */
     protected Bundle mEditorMetadata;
 
+    /**
+     * @hide
+     */
+    protected MediaMetadata.Builder mMetadataBuilder;
 
     /**
      * Clears all the pending metadata changes set since the MediaMetadataEditor instance was
@@ -120,6 +125,7 @@
         }
         mEditorMetadata.clear();
         mEditorArtwork = null;
+        mMetadataBuilder = new MediaMetadata.Builder();
     }
 
     /**
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index c2c61d3..8368df94 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -24,6 +24,11 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.RectF;
+import android.media.session.MediaMetadata;
+import android.media.session.MediaSessionLegacyHelper;
+import android.media.session.PlaybackState;
+import android.media.session.Session;
+import android.media.session.TransportPerformer;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -336,6 +341,8 @@
      */
     public final static int FLAG_INFORMATION_REQUEST_ALBUM_ART = 1 << 3;
 
+    private Session mSession;
+
     /**
      * Class constructor.
      * @param mediaButtonIntent The intent that will be sent for the media button events sent
@@ -385,6 +392,22 @@
     }
 
     /**
+     * @hide
+     */
+    public void registerWithSession(MediaSessionLegacyHelper helper) {
+        helper.addRccListener(mRcMediaIntent, mTransportListener);
+        mSession = helper.getSession(mRcMediaIntent);
+    }
+
+    /**
+     * @hide
+     */
+    public void unregisterWithSession(MediaSessionLegacyHelper helper) {
+        helper.removeRccListener(mRcMediaIntent);
+        mSession = null;
+    }
+
+    /**
      * Class used to modify metadata in a {@link RemoteControlClient} object.
      * Use {@link RemoteControlClient#editMetadata(boolean)} to create an instance of an editor,
      * on which you set the metadata for the RemoteControlClient instance. Once all the information
@@ -438,6 +461,15 @@
         public synchronized MetadataEditor putString(int key, String value)
                 throws IllegalArgumentException {
             super.putString(key, value);
+            if (mMetadataBuilder != null) {
+                // MediaMetadata supports all the same fields as MetadataEditor
+                String metadataKey = MediaMetadata.getKeyFromMetadataEditorKey(key);
+                // But just in case, don't add things we don't understand
+                if (metadataKey != null) {
+                    mMetadataBuilder.putString(metadataKey, value);
+                }
+            }
+
             return this;
         }
 
@@ -459,6 +491,14 @@
         public synchronized MetadataEditor putLong(int key, long value)
                 throws IllegalArgumentException {
             super.putLong(key, value);
+            if (mMetadataBuilder != null) {
+                // MediaMetadata supports all the same fields as MetadataEditor
+                String metadataKey = MediaMetadata.getKeyFromMetadataEditorKey(key);
+                // But just in case, don't add things we don't understand
+                if (metadataKey != null) {
+                    mMetadataBuilder.putLong(metadataKey, value);
+                }
+            }
             return this;
         }
 
@@ -476,6 +516,14 @@
         public synchronized MetadataEditor putBitmap(int key, Bitmap bitmap)
                 throws IllegalArgumentException {
             super.putBitmap(key, bitmap);
+            if (mMetadataBuilder != null) {
+                // MediaMetadata supports all the same fields as MetadataEditor
+                String metadataKey = MediaMetadata.getKeyFromMetadataEditorKey(key);
+                // But just in case, don't add things we don't understand
+                if (metadataKey != null) {
+                    mMetadataBuilder.putBitmap(metadataKey, bitmap);
+                }
+            }
             return this;
         }
 
@@ -501,7 +549,7 @@
                 Log.e(TAG, "Can't apply a previously applied MetadataEditor");
                 return;
             }
-            synchronized(mCacheLock) {
+            synchronized (mCacheLock) {
                 // assign the edited data
                 mMetadata = new Bundle(mEditorMetadata);
                 // add the information about editable keys
@@ -521,6 +569,11 @@
                     // send to remote control display if conditions are met
                     sendArtwork_syncCacheLock(null, 0, 0);
                 }
+
+                // USE_SESSIONS
+                if (mSession != null && mMetadataBuilder != null) {
+                    mSession.getTransportPerformer().setMetadata(mMetadataBuilder.build());
+                }
                 mApplied = true;
             }
         }
@@ -546,6 +599,12 @@
             editor.mMetadataChanged = false;
             editor.mArtworkChanged = false;
         }
+        // USE_SESSIONS
+        if (startEmpty || mMediaMetadata == null) {
+            editor.mMetadataBuilder = new MediaMetadata.Builder();
+        } else {
+            editor.mMetadataBuilder = new MediaMetadata.Builder(mMediaMetadata);
+        }
         return editor;
     }
 
@@ -624,6 +683,15 @@
 
                 // handle automatic playback position refreshes
                 initiateCheckForDrift_syncCacheLock();
+
+                // USE_SESSIONS
+                if (mSession != null) {
+                    int pbState = PlaybackState.getStateFromRccState(state);
+                    mSessionPlaybackState.setState(pbState, hasPosition ?
+                            mPlaybackPositionMs : PlaybackState.PLAYBACK_POSITION_UNKNOWN,
+                            playbackSpeed);
+                    mSession.getTransportPerformer().setPlaybackState(mSessionPlaybackState);
+                }
             }
         }
     }
@@ -704,6 +772,13 @@
 
             // send to remote control display if conditions are met
             sendTransportControlInfo_syncCacheLock(null);
+
+            // USE_SESSIONS
+            if (mSession != null) {
+                mSessionPlaybackState.setActions(PlaybackState
+                        .getActionsFromRccControlFlags(transportControlFlags));
+                mSession.getTransportPerformer().setPlaybackState(mSessionPlaybackState);
+            }
         }
     }
 
@@ -1038,6 +1113,16 @@
     private boolean mNeedsPositionSync = false;
 
     /**
+     * Cache for the current playback state using Session APIs.
+     */
+    private final PlaybackState mSessionPlaybackState = new PlaybackState();
+
+    /**
+     * Cache for metadata using Session APIs. This is re-initialized in apply().
+     */
+    private MediaMetadata mMediaMetadata;
+
+    /**
      * A class to encapsulate all the information about a remote control display.
      * A RemoteControlClient's metadata and state may be displayed on multiple IRemoteControlDisplay
      */
@@ -1219,6 +1304,26 @@
         return mRcseId;
     }
 
+    // USE_SESSIONS
+    private TransportPerformer.Listener mTransportListener = new TransportPerformer.Listener() {
+
+        @Override
+        public void onSeekTo(long pos) {
+            RemoteControlClient.this.onSeekTo(mCurrentClientGenId, pos);
+        }
+
+        @Override
+        public void onRate(Rating rating) {
+            if ((mTransportControlFlags & FLAG_KEY_MEDIA_RATING) != 0) {
+                if (mEventHandler != null) {
+                    mEventHandler.sendMessage(mEventHandler.obtainMessage(
+                            MSG_UPDATE_METADATA, mCurrentClientGenId,
+                            MetadataEditor.RATING_KEY_BY_USER, rating));
+                }
+            }
+        }
+    };
+
     private EventHandler mEventHandler;
     private final static int MSG_REQUEST_PLAYBACK_STATE = 1;
     private final static int MSG_REQUEST_METADATA = 2;
@@ -1325,7 +1430,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mEnabled) {
                     try {
                         di.mRcDisplay.setPlaybackState(mInternalClientGenId,
@@ -1353,7 +1458,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mEnabled) {
                     try {
                         di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata);
@@ -1381,7 +1486,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mEnabled) {
                     try {
                         di.mRcDisplay.setTransportControlInfo(mInternalClientGenId,
@@ -1407,7 +1512,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                if (!sendArtworkToDisplay((DisplayInfoForClient) displayIterator.next())) {
+                if (!sendArtworkToDisplay(displayIterator.next())) {
                     displayIterator.remove();
                 }
             }
@@ -1453,7 +1558,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 try {
                     if (di.mEnabled) {
                         if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) {
@@ -1537,7 +1642,7 @@
             boolean displayKnown = false;
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext() && !displayKnown) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 displayKnown = di.mRcDisplay.asBinder().equals(rcd.asBinder());
                 if (displayKnown) {
                     // this display was known but the change in artwork size will cause the
@@ -1562,7 +1667,7 @@
         synchronized(mCacheLock) {
             Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
                     displayIterator.remove();
                     break;
@@ -1573,7 +1678,7 @@
             boolean newNeedsPositionSync = false;
             displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mWantsPositionSync) {
                     newNeedsPositionSync = true;
                     break;
@@ -1592,7 +1697,7 @@
         synchronized(mCacheLock) {
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mRcDisplay.asBinder().equals(rcd.asBinder()) &&
                         ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h))) {
                     di.mArtworkExpectedWidth = w;
@@ -1617,7 +1722,7 @@
             // go through the list of RCDs and for each entry, check both whether this is the RCD
             //  that gets upated, and whether the list has one entry that wants position sync
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mEnabled) {
                     if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
                         di.mWantsPositionSync = wantsSync;
@@ -1640,7 +1745,7 @@
         synchronized(mCacheLock) {
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
                     di.mEnabled = enable;
                 }
diff --git a/media/java/android/media/routeprovider/RouteRequest.java b/media/java/android/media/routeprovider/RouteRequest.java
index 9913566..68475c0 100644
--- a/media/java/android/media/routeprovider/RouteRequest.java
+++ b/media/java/android/media/routeprovider/RouteRequest.java
@@ -20,6 +20,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.io.PrintWriter;
+
 /**
  * A request to connect or discover routes with certain capabilities.
  * <p>
@@ -70,6 +72,17 @@
     }
 
     @Override
+    public String toString() {
+        StringBuilder bob = new StringBuilder();
+        bob.append("RouteRequest {");
+        bob.append("active=").append(mActive);
+        bob.append(", info=").append(mSessionInfo.toString());
+        bob.append(", options=").append(mOptions.toString());
+        bob.append("}");
+        return bob.toString();
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
diff --git a/media/java/android/media/session/MediaMetadata.java b/media/java/android/media/session/MediaMetadata.java
index e2330f7..8a8af45 100644
--- a/media/java/android/media/session/MediaMetadata.java
+++ b/media/java/android/media/session/MediaMetadata.java
@@ -16,12 +16,15 @@
 package android.media.session;
 
 import android.graphics.Bitmap;
+import android.media.MediaMetadataEditor;
+import android.media.MediaMetadataRetriever;
 import android.media.Rating;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.SparseArray;
 
 /**
  * Contains metadata about an item, such as the title, artist, etc.
@@ -40,7 +43,8 @@
     public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
 
     /**
-     * The duration of the media in ms. A duration of 0 is the default.
+     * The duration of the media in ms. A negative duration indicates that the
+     * duration is unknown (or infinite).
      */
     public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
 
@@ -65,12 +69,17 @@
     public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
 
     /**
+     * The compilation status of the media.
+     */
+    public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
+
+    /**
      * The date the media was created or published as TODO determine format.
      */
     public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
 
     /**
-     * The year the media was created or published as a numeric String.
+     * The year the media was created or published as a long.
      */
     public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
 
@@ -151,8 +160,9 @@
         METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_STRING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_STRING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_STRING);
+        METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_STRING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_STRING);
-        METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_STRING);
+        METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG);
         METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_STRING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG);
         METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG);
@@ -165,6 +175,36 @@
         METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING);
     }
+
+    private static final SparseArray<String> EDITOR_KEY_MAPPING;
+
+    static {
+        EDITOR_KEY_MAPPING = new SparseArray<String>();
+        EDITOR_KEY_MAPPING.put(MediaMetadataEditor.BITMAP_KEY_ARTWORK, METADATA_KEY_ART);
+        EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_OTHERS, METADATA_KEY_RATING);
+        EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_USER, METADATA_KEY_USER_RATING);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUM, METADATA_KEY_ALBUM);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST,
+                METADATA_KEY_ALBUM_ARTIST);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ARTIST, METADATA_KEY_ARTIST);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_AUTHOR, METADATA_KEY_AUTHOR);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER,
+                METADATA_KEY_TRACK_NUMBER);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPOSER, METADATA_KEY_COMPOSER);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPILATION,
+                METADATA_KEY_COMPILATION);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DATE, METADATA_KEY_DATE);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER,
+                METADATA_KEY_DISC_NUMBER);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DURATION, METADATA_KEY_DURATION);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_GENRE, METADATA_KEY_GENRE);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS,
+                METADATA_KEY_NUM_TRACKS);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_TITLE, METADATA_KEY_TITLE);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_WRITER, METADATA_KEY_WRITER);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_YEAR, METADATA_KEY_YEAR);
+    }
+
     private final Bundle mBundle;
 
     private MediaMetadata(Bundle bundle) {
@@ -176,6 +216,16 @@
     }
 
     /**
+     * Returns true if the given key is contained in the metadata
+     *
+     * @param key a String key
+     * @return true if the key exists in this metadata, false otherwise
+     */
+    public boolean containsKey(String key) {
+        return mBundle.containsKey(key);
+    }
+
+    /**
      * Returns the value associated with the given key, or null if no mapping of
      * the desired type exists for the given key or a null value is explicitly
      * associated with the key.
@@ -195,7 +245,7 @@
      * @return a long value
      */
     public long getLong(String key) {
-        return mBundle.getLong(key);
+        return mBundle.getLong(key, 0);
     }
 
     /**
@@ -244,6 +294,27 @@
         dest.writeBundle(mBundle);
     }
 
+    /**
+     * Get the number of fields in this metadata.
+     *
+     * @return The number of fields in the metadata.
+     */
+    public int size() {
+        return mBundle.size();
+    }
+
+    /**
+     * Helper for getting the String key used by {@link MediaMetadata} from the
+     * integer key that {@link MediaMetadataEditor} uses.
+     *
+     * @param editorKey The key used by the editor
+     * @return The key used by this class or null if no mapping exists
+     * @hide
+     */
+    public static String getKeyFromMetadataEditorKey(int editorKey) {
+        return EDITOR_KEY_MAPPING.get(editorKey, null);
+    }
+
     public static final Parcelable.Creator<MediaMetadata> CREATOR
             = new Parcelable.Creator<MediaMetadata>() {
                 @Override
@@ -295,10 +366,9 @@
          * <li>{@link #METADATA_KEY_WRITER}</li>
          * <li>{@link #METADATA_KEY_COMPOSER}</li>
          * <li>{@link #METADATA_KEY_DATE}</li>
-         * <li>{@link #METADATA_KEY_YEAR}</li>
          * <li>{@link #METADATA_KEY_GENRE}</li>
-         * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li>li>
-         * <li>{@link #METADATA_KEY_ART_URI}</li>li>
+         * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li>
+         * <li>{@link #METADATA_KEY_ART_URI}</li>
          * <li>{@link #METADATA_KEY_ALBUM_ART_URI}</li>
          * </ul>
          *
@@ -326,6 +396,7 @@
          * <li>{@link #METADATA_KEY_TRACK_NUMBER}</li>
          * <li>{@link #METADATA_KEY_NUM_TRACKS}</li>
          * <li>{@link #METADATA_KEY_DISC_NUMBER}</li>
+         * <li>{@link #METADATA_KEY_YEAR}</li>
          * </ul>
          *
          * @param key The key for referencing this value
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
new file mode 100644
index 0000000..4ee67d1
--- /dev/null
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.view.KeyEvent;
+
+/**
+ * Helper for connecting existing APIs up to the new session APIs. This can be
+ * used by RCC, AudioFocus, etc. to create a single session that translates to
+ * all those components.
+ *
+ * @hide
+ */
+public class MediaSessionLegacyHelper {
+    private static final String TAG = "MediaSessionHelper";
+
+    private static final Object sLock = new Object();
+    private static MediaSessionLegacyHelper sInstance;
+
+    private SessionManager mSessionManager;
+    private Handler mHandler = new Handler(Looper.getMainLooper());
+    // The legacy APIs use PendingIntents to register/unregister media button
+    // receivers and these are associated with RCC.
+    private ArrayMap<PendingIntent, SessionHolder> mSessions = new ArrayMap<PendingIntent, SessionHolder>();
+
+    private MediaSessionLegacyHelper(Context context) {
+        mSessionManager = (SessionManager) context
+                .getSystemService(Context.MEDIA_SESSION_SERVICE);
+    }
+
+    public static MediaSessionLegacyHelper getHelper(Context context) {
+        synchronized (sLock) {
+            if (sInstance == null) {
+                sInstance = new MediaSessionLegacyHelper(context);
+            }
+        }
+        return sInstance;
+    }
+
+    public Session getSession(PendingIntent pi) {
+        SessionHolder holder = mSessions.get(pi);
+        return holder == null ? null : holder.mSession;
+    }
+
+    public void addRccListener(PendingIntent pi, TransportPerformer.Listener listener) {
+
+        SessionHolder holder = getHolder(pi, true);
+        TransportPerformer performer = holder.mSession.getTransportPerformer();
+        if (holder.mRccListener != null) {
+            if (holder.mRccListener == listener) {
+                // This is already the registered listener, ignore
+                return;
+            }
+            // Otherwise it changed so we need to switch to the new one
+            performer.removeListener(holder.mRccListener);
+        }
+        performer.addListener(listener, mHandler);
+        holder.mRccListener = listener;
+        holder.update();
+    }
+
+    public void removeRccListener(PendingIntent pi) {
+        SessionHolder holder = getHolder(pi, false);
+        if (holder != null && holder.mRccListener != null) {
+            holder.mSession.getTransportPerformer().removeListener(holder.mRccListener);
+            holder.mRccListener = null;
+            holder.update();
+        }
+    }
+
+    public void addMediaButtonListener(PendingIntent pi,
+            Context context) {
+        SessionHolder holder = getHolder(pi, true);
+        if (holder.mMediaButtonListener != null) {
+            // Already have this listener registered
+            return;
+        }
+        holder.mMediaButtonListener = new MediaButtonListener(pi, context);
+        holder.mSession.getTransportPerformer().addListener(holder.mMediaButtonListener, mHandler);
+    }
+
+    public void removeMediaButtonListener(PendingIntent pi) {
+        SessionHolder holder = getHolder(pi, false);
+        if (holder != null && holder.mMediaButtonListener != null) {
+            holder.mSession.getTransportPerformer().removeListener(holder.mMediaButtonListener);
+            holder.update();
+        }
+    }
+
+    private SessionHolder getHolder(PendingIntent pi, boolean createIfMissing) {
+        SessionHolder holder = mSessions.get(pi);
+        if (holder == null && createIfMissing) {
+            Session session = mSessionManager.createSession(TAG);
+            session.setTransportPerformerEnabled();
+            session.publish();
+            holder = new SessionHolder(session, pi);
+            mSessions.put(pi, holder);
+        }
+        return holder;
+    }
+
+    public static class MediaButtonListener extends TransportPerformer.Listener {
+        private final PendingIntent mPendingIntent;
+        private final Context mContext;
+
+        public MediaButtonListener(PendingIntent pi, Context context) {
+            mPendingIntent = pi;
+            mContext = context;
+        }
+
+        @Override
+        public void onPlay() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_PLAY);
+        }
+
+        @Override
+        public void onPause() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_PAUSE);
+        }
+
+        @Override
+        public void onNext() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_NEXT);
+        }
+
+        @Override
+        public void onPrevious() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
+        }
+
+        @Override
+        public void onFastForward() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD);
+        }
+
+        @Override
+        public void onRewind() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_REWIND);
+        }
+
+        @Override
+        public void onStop() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_STOP);
+        }
+
+        private void sendKeyEvent(int keyCode) {
+            KeyEvent ke = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
+            Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+
+            intent.putExtra(Intent.EXTRA_KEY_EVENT, ke);
+            try {
+                mPendingIntent.send(mContext, 0, intent);
+            } catch (CanceledException e) {
+                Log.e(TAG, "Error sending media key down event:", e);
+                // Don't bother sending up if down failed
+                return;
+            }
+
+            ke = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
+            intent.putExtra(Intent.EXTRA_KEY_EVENT, ke);
+            try {
+                mPendingIntent.send(mContext, 0, intent);
+            } catch (CanceledException e) {
+                Log.e(TAG, "Error sending media key up event:", e);
+            }
+        }
+    }
+
+    private class SessionHolder {
+        public final Session mSession;
+        public final PendingIntent mPi;
+        public MediaButtonListener mMediaButtonListener;
+        public TransportPerformer.Listener mRccListener;
+
+        public SessionHolder(Session session, PendingIntent pi) {
+            mSession = session;
+            mPi = pi;
+        }
+
+        public void update() {
+            if (mMediaButtonListener == null && mRccListener == null) {
+                mSession.release();
+                mSessions.remove(mPi);
+            } else if (mMediaButtonListener != null && mRccListener != null) {
+                // TODO set session to active
+            } else {
+                // TODO set session to inactive
+            }
+        }
+    }
+}
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 14d9fb1..3254e5d 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -15,8 +15,10 @@
  */
 package android.media.session;
 
+import android.media.RemoteControlClient;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 
 /**
  * Playback state for a {@link Session}. This includes a state like
@@ -88,6 +90,13 @@
     public static final long ACTION_SEEK_TO = 1 << 8;
 
     /**
+     * Indicates this performer supports the play/pause toggle command.
+     *
+     * @see #setActions
+     */
+    public static final long ACTION_PLAY_PAUSE = 1 << 9;
+
+    /**
      * This is the default playback state and indicates that no media has been
      * added yet, or the performer has been reset and has no content to play.
      *
@@ -154,12 +163,32 @@
      */
     public final static int PLAYSTATE_CONNECTING = 8;
 
+    /**
+     * State indicating the player is currently skipping to the previous item.
+     *
+     * @see #setState
+     */
+    public final static int PLAYSTATE_SKIPPING_BACKWARDS = 9;
+
+    /**
+     * State indicating the player is currently skipping to the next item.
+     *
+     * @see #setState
+     */
+    public final static int PLAYSTATE_SKIPPING_FORWARDS = 10;
+
+    /**
+     * Use this value for the position to indicate the position is not known.
+     */
+    public final static long PLAYBACK_POSITION_UNKNOWN = -1;
+
     private int mState;
     private long mPosition;
     private long mBufferPosition;
-    private float mSpeed;
-    private long mCapabilities;
+    private float mRate;
+    private long mActions;
     private String mErrorMessage;
+    private long mUpdateTime;
 
     /**
      * Create an empty PlaybackState. At minimum a state and actions should be
@@ -175,21 +204,38 @@
      * @param from The PlaybackState to duplicate
      */
     public PlaybackState(PlaybackState from) {
-        this.setState(from.getState());
-        this.setPosition(from.getPosition());
-        this.setBufferPosition(from.getBufferPosition());
-        this.setSpeed(from.getSpeed());
-        this.setActions(from.getActions());
-        this.setErrorMessage(from.getErrorMessage());
+        mState = from.mState;
+        mPosition = from.mPosition;
+        mRate = from.mRate;
+        mUpdateTime = from.mUpdateTime;
+        mBufferPosition = from.mBufferPosition;
+        mActions = from.mActions;
+        mErrorMessage = from.mErrorMessage;
     }
 
     private PlaybackState(Parcel in) {
-        this.setState(in.readInt());
-        this.setPosition(in.readLong());
-        this.setBufferPosition(in.readLong());
-        this.setSpeed(in.readFloat());
-        this.setActions(in.readLong());
-        this.setErrorMessage(in.readString());
+        mState = in.readInt();
+        mPosition = in.readLong();
+        mRate = in.readFloat();
+        mUpdateTime = in.readLong();
+        mBufferPosition = in.readLong();
+        mActions = in.readLong();
+        mErrorMessage = in.readString();
+
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder bob = new StringBuilder("PlaybackState {");
+        bob.append("state=").append(mState);
+        bob.append(", position=").append(mPosition);
+        bob.append(", buffered position=").append(mBufferPosition);
+        bob.append(", rate=").append(mRate);
+        bob.append(", updated=").append(mUpdateTime);
+        bob.append(", actions=").append(mActions);
+        bob.append(", error=").append(mErrorMessage);
+        bob.append("}");
+        return bob.toString();
     }
 
     @Override
@@ -199,12 +245,13 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(getState());
-        dest.writeLong(getPosition());
-        dest.writeLong(getBufferPosition());
-        dest.writeFloat(getSpeed());
-        dest.writeLong(getActions());
-        dest.writeString(getErrorMessage());
+        dest.writeInt(mState);
+        dest.writeLong(mPosition);
+        dest.writeFloat(mRate);
+        dest.writeLong(mUpdateTime);
+        dest.writeLong(mBufferPosition);
+        dest.writeLong(mActions);
+        dest.writeString(mErrorMessage);
     }
 
     /**
@@ -224,7 +271,16 @@
     }
 
     /**
-     * Set the current state of playback. One of the following:
+     * Set the current state of playback.
+     * <p>
+     * The position must be in ms and indicates the current playback position
+     * within the track. If the position is unknown use
+     * {@link #PLAYBACK_POSITION_UNKNOWN}.
+     * <p>
+     * The rate is a multiple of normal playback and should be 0 when paused and
+     * negative when rewinding. Normal playback rate is 1.0.
+     * <p>
+     * The state must be one of the following:
      * <ul>
      * <li> {@link PlaybackState#PLAYSTATE_NONE}</li>
      * <li> {@link PlaybackState#PLAYSTATE_STOPPED}</li>
@@ -234,9 +290,18 @@
      * <li> {@link PlaybackState#PLAYSTATE_REWINDING}</li>
      * <li> {@link PlaybackState#PLAYSTATE_BUFFERING}</li>
      * <li> {@link PlaybackState#PLAYSTATE_ERROR}</li>
+     * </ul>
+     *
+     * @param state The current state of playback.
+     * @param position The position in the current track in ms.
+     * @param rate The current rate of playback as a multiple of normal
+     *            playback.
      */
-    public void setState(int mState) {
-        this.mState = mState;
+    public void setState(int state, long position, float rate) {
+        this.mState = state;
+        this.mPosition = position;
+        this.mRate = rate;
+        mUpdateTime = SystemClock.elapsedRealtime();
     }
 
     /**
@@ -247,13 +312,6 @@
     }
 
     /**
-     * Set the current playback position in ms.
-     */
-    public void setPosition(long position) {
-        mPosition = position;
-    }
-
-    /**
      * Get the current buffer position in ms. This is the farthest playback
      * point that can be reached from the current position using only buffered
      * content.
@@ -272,21 +330,14 @@
     }
 
     /**
-     * Get the current playback speed as a multiple of normal playback. This
+     * Get the current playback rate as a multiple of normal playback. This
      * should be negative when rewinding. A value of 1 means normal playback and
      * 0 means paused.
+     *
+     * @return The current rate of playback.
      */
-    public float getSpeed() {
-        return mSpeed;
-    }
-
-    /**
-     * Set the current playback speed as a multiple of normal playback. This
-     * should be negative when rewinding. A value of 1 means normal playback and
-     * 0 means paused.
-     */
-    public void setSpeed(float speed) {
-        mSpeed = speed;
+    public float getRate() {
+        return mRate;
     }
 
     /**
@@ -305,7 +356,7 @@
      * </ul>
      */
     public long getActions() {
-        return mCapabilities;
+        return mActions;
     }
 
     /**
@@ -324,7 +375,7 @@
      * </ul>
      */
     public void setActions(long capabilities) {
-        mCapabilities = capabilities;
+        mActions = capabilities;
     }
 
     /**
@@ -336,6 +387,17 @@
     }
 
     /**
+     * Get the elapsed real time at which position was last updated. If the
+     * position has never been set this will return 0;
+     *
+     * @return The last time the position was updated.
+     * @hide
+     */
+    public long getLastPositionUpdateTime() {
+        return mUpdateTime;
+    }
+
+    /**
      * Set a user readable error message. This should be set when the state is
      * {@link PlaybackState#PLAYSTATE_ERROR}.
      */
@@ -343,6 +405,80 @@
         mErrorMessage = errorMessage;
     }
 
+    /**
+     * Get the {@link PlaybackState} state for the given
+     * {@link RemoteControlClient} state.
+     *
+     * @param rccState The state used by {@link RemoteControlClient}.
+     * @return The equivalent state used by {@link PlaybackState}.
+     * @hide
+     */
+    public static int getStateFromRccState(int rccState) {
+        switch (rccState) {
+            case RemoteControlClient.PLAYSTATE_BUFFERING:
+                return PLAYSTATE_BUFFERING;
+            case RemoteControlClient.PLAYSTATE_ERROR:
+                return PLAYSTATE_ERROR;
+            case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
+                return PLAYSTATE_FAST_FORWARDING;
+            case RemoteControlClient.PLAYSTATE_NONE:
+                return PLAYSTATE_NONE;
+            case RemoteControlClient.PLAYSTATE_PAUSED:
+                return PLAYSTATE_PAUSED;
+            case RemoteControlClient.PLAYSTATE_PLAYING:
+                return PLAYSTATE_PLAYING;
+            case RemoteControlClient.PLAYSTATE_REWINDING:
+                return PLAYSTATE_REWINDING;
+            case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
+                return PLAYSTATE_SKIPPING_BACKWARDS;
+            case RemoteControlClient.PLAYSTATE_STOPPED:
+                return PLAYSTATE_STOPPED;
+            default:
+                return -1;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static long getActionsFromRccControlFlags(int rccFlags) {
+        long actions = 0;
+        long flag = 1;
+        while (flag <= rccFlags) {
+            if ((flag & rccFlags) != 0) {
+                actions |= getActionForRccFlag((int) flag);
+            }
+            flag = flag << 1;
+        }
+        return actions;
+    }
+
+    private static long getActionForRccFlag(int flag) {
+        switch (flag) {
+            case RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS:
+                return ACTION_PREVIOUS_ITEM;
+            case RemoteControlClient.FLAG_KEY_MEDIA_REWIND:
+                return ACTION_REWIND;
+            case RemoteControlClient.FLAG_KEY_MEDIA_PLAY:
+                return ACTION_PLAY;
+            case RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE:
+                return ACTION_PLAY_PAUSE;
+            case RemoteControlClient.FLAG_KEY_MEDIA_PAUSE:
+                return ACTION_PAUSE;
+            case RemoteControlClient.FLAG_KEY_MEDIA_STOP:
+                return ACTION_STOP;
+            case RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD:
+                return ACTION_FASTFORWARD;
+            case RemoteControlClient.FLAG_KEY_MEDIA_NEXT:
+                return ACTION_NEXT_ITEM;
+            case RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE:
+                return ACTION_SEEK_TO;
+            case RemoteControlClient.FLAG_KEY_MEDIA_RATING:
+                return ACTION_RATING;
+        }
+        return 0;
+    }
+
     public static final Parcelable.Creator<PlaybackState> CREATOR
             = new Parcelable.Creator<PlaybackState>() {
         @Override
diff --git a/media/java/android/media/session/SessionInfo.java b/media/java/android/media/session/SessionInfo.java
index 22d8ab1..2b65528 100644
--- a/media/java/android/media/session/SessionInfo.java
+++ b/media/java/android/media/session/SessionInfo.java
@@ -57,6 +57,11 @@
     }
 
     @Override
+    public String toString() {
+        return "SessionInfo {id=" + mId + ", pkg=" + mPackageName + "}";
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
diff --git a/media/java/android/media/session/TransportPerformer.java b/media/java/android/media/session/TransportPerformer.java
index eddffd1..187f48d 100644
--- a/media/java/android/media/session/TransportPerformer.java
+++ b/media/java/android/media/session/TransportPerformer.java
@@ -280,18 +280,11 @@
         /**
          * Report that audio focus has changed on the app. This only happens if
          * you have indicated you have started playing with
-         * {@link #setPlaybackState}. TODO figure out route focus apis/handling.
+         * {@link #setPlaybackState}.
          *
-         * @param focusChange The type of focus change, TBD. The default
-         *            implementation will deliver a call to {@link #onPause}
-         *            when focus is lost.
+         * @param focusChange The type of focus change, TBD.
          */
         public void onRouteFocusChange(int focusChange) {
-            switch (focusChange) {
-                case AudioManager.AUDIOFOCUS_LOSS:
-                    onPause();
-                    break;
-            }
         }
     }
 
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index d04b1f8..a710c03 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -255,7 +255,7 @@
             env, env->FindClass("android/media/MediaCodec$BufferInfo"));
 
     jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
-    env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags);
+    env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags);
 
     return OK;
 }
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 4e42ae3..157dd49 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -273,6 +273,13 @@
                             width,
                             height,
                             config);
+    if (jBitmap == NULL) {
+        if (env->ExceptionCheck()) {
+            env->ExceptionClear();
+        }
+        ALOGE("getFrameAtTime: create Bitmap failed!");
+        return NULL;
+    }
 
     SkBitmap *bitmap =
             (SkBitmap *) env->GetLongField(jBitmap, fields.nativeBitmap);
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index 492fde7..af7c282 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -29,7 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Lagre"</string>
     <string name="menu_share" msgid="3075149983979628146">"Del"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Slett"</string>
-    <string name="menu_select" msgid="8711270657353563424">"Velg <xliff:g id="DIRECTORY">^1</xliff:g>"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Velg «<xliff:g id="DIRECTORY">^1</xliff:g>»"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> valgt"</string>
     <string name="sort_name" msgid="9183560467917256779">"Etter navn"</string>
     <string name="sort_date" msgid="586080032956151448">"«Etter dato» endret"</string>
diff --git a/packages/InputDevices/res/raw/keyboard_layout_czech.kcm b/packages/InputDevices/res/raw/keyboard_layout_czech.kcm
index f710a8e..dc614db 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_czech.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_czech.kcm
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 #
-# Czech keyboard layout.
+# Czech (EU - qwerty) keyboard layout.
 #
 
 type OVERLAY
@@ -26,6 +26,8 @@
     label:                              ';'
     base:                               ';'
     shift:                              '\u00b0'
+    ralt:                               '\u0060'
+    shift+ralt:                         '\u007e'
 }
 
 key 1 {
@@ -38,6 +40,7 @@
 key 2 {
     label:                              '2'
     base:                               '\u011b'
+    capslock:                           '\u011a'
     shift:                              '2'
     ralt:                               '@'
 }
@@ -45,6 +48,7 @@
 key 3 {
     label:                              '3'
     base:                               '\u0161'
+    capslock:                           '\u0160'
     shift:                              '3'
     ralt:                               '#'
 }
@@ -52,6 +56,7 @@
 key 4 {
     label:                              '4'
     base:                               '\u010d'
+    capslock:                           '\u010c'
     shift:                              '4'
     ralt:                               '$'
 }
@@ -59,6 +64,7 @@
 key 5 {
     label:                              '5'
     base:                               '\u0159'
+    capslock:                           '\u0158'
     shift:                              '5'
     ralt:                               '%'
 }
@@ -66,6 +72,7 @@
 key 6 {
     label:                              '6'
     base:                               '\u017e'
+    capslock:                           '\u017d'
     shift:                              '6'
     ralt:                               '^'
 }
@@ -73,6 +80,7 @@
 key 7 {
     label:                              '7'
     base:                               '\u00fd'
+    capslock:                           '\u00dd'
     shift:                              '7'
     ralt:                               '&'
 }
@@ -80,6 +88,7 @@
 key 8 {
     label:                              '8'
     base:                               '\u00e1'
+    capslock:                           '\u00c1'
     shift:                              '8'
     ralt:                               '*'
 }
@@ -87,6 +96,7 @@
 key 9 {
     label:                              '9'
     base:                               '\u00ed'
+    capslock:                           '\u00cd'
     shift:                              '9'
     ralt:                               '('
 }
@@ -94,6 +104,7 @@
 key 0 {
     label:                              '0'
     base:                               '\u00e9'
+    capslock:                           '\u00c9'
     shift:                              '0'
     ralt:                               ')'
 }
@@ -180,6 +191,7 @@
 key LEFT_BRACKET {
     label:                              '\u00fa'
     base:                               '\u00fa'
+    capslock:                           '\u00da'
     shift:                              '/'
     ralt:                               '['
     ralt+shift:                         '{'
@@ -252,6 +264,7 @@
 key SEMICOLON {
     label:                              '\u016f'
     base:                               '\u016f'
+    capslock:                           '\u016e'
     shift:                              '"'
     ralt:                               ';'
     ralt+shift:                         ':'
@@ -261,8 +274,8 @@
     label:                              '\u00a7'
     base:                               '\u00a7'
     shift:                              '!'
-    ralt:                               '\''
-    ralt+shift:                         '"'
+    ralt:                               '\u00a4'
+    ralt+shift:                         '\u005e'
 }
 
 key BACKSLASH {
@@ -279,6 +292,8 @@
     label:                              '\\'
     base:                               '\\'
     shift:                              '|'
+    ralt:                               '\u00df'
+    shift+ralt:                         '\u02dd'
 }
 
 key Z {
@@ -330,6 +345,7 @@
     base:                               ','
     shift:                              '?'
     ralt:                               '<'
+    shift+ralt:                         '\u00d7'
 }
 
 key PERIOD {
@@ -337,6 +353,7 @@
     base:                               '.'
     shift:                              ':'
     ralt:                               '>'
+    shift+ralt:                         '\u00f7'
 }
 
 key SLASH {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm b/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm
index 0fabf02..66c1c98 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm
@@ -122,7 +122,7 @@
     base:                               'q'
     shift, capslock:                    'Q'
     ralt:                               '\u00e4'
-    shift+ralt:                         '\u00c4'
+    shift+ralt, capslock+ralt:          '\u00c4'
 }
 
 key W {
@@ -130,7 +130,7 @@
     base:                               'w'
     shift, capslock:                    'W'
     ralt:                               '\u00e5'
-    shift+ralt:                         '\u00c5'
+    shift+ralt, capslock+ralt:          '\u00c5'
 }
 
 key E {
@@ -138,7 +138,7 @@
     base:                               'e'
     shift, capslock:                    'E'
     ralt:                               '\u00e9'
-    shift+ralt:                         '\u00c9'
+    shift+ralt, capslock+ralt:          '\u00c9'
 }
 
 key R {
@@ -153,7 +153,7 @@
     base:                               't'
     shift, capslock:                    'T'
     ralt:                               '\u00fe'
-    shift+ralt:                         '\u00de'
+    shift+ralt, capslock+ralt:          '\u00de'
 }
 
 key Y {
@@ -161,7 +161,7 @@
     base:                               'y'
     shift, capslock:                    'Y'
     ralt:                               '\u00fc'
-    shift+ralt:                         '\u00dc'
+    shift+ralt, capslock+ralt:          '\u00dc'
 }
 
 key U {
@@ -169,7 +169,7 @@
     base:                               'u'
     shift, capslock:                    'U'
     ralt:                               '\u00fa'
-    shift+ralt:                         '\u00da'
+    shift+ralt, capslock+ralt:          '\u00da'
 }
 
 key I {
@@ -177,7 +177,7 @@
     base:                               'i'
     shift, capslock:                    'I'
     ralt:                               '\u00ed'
-    shift+ralt:                         '\u00cd'
+    shift+ralt, capslock+ralt:          '\u00cd'
 }
 
 key O {
@@ -185,7 +185,7 @@
     base:                               'o'
     shift, capslock:                    'O'
     ralt:                               '\u00f3'
-    shift+ralt:                         '\u00d3'
+    shift+ralt, capslock+ralt:          '\u00d3'
 }
 
 key P {
@@ -193,7 +193,7 @@
     base:                               'p'
     shift, capslock:                    'P'
     ralt:                               '\u00f6'
-    shift+ralt:                         '\u00d6'
+    shift+ralt, capslock+ralt:          '\u00d6'
 }
 
 key LEFT_BRACKET {
@@ -225,7 +225,7 @@
     base:                               'a'
     shift, capslock:                    'A'
     ralt:                               '\u00e1'
-    shift+ralt:                         '\u00c1'
+    shift+ralt, ralt+capslock:          '\u00c1'
 }
 
 key S {
@@ -241,7 +241,7 @@
     base:                               'd'
     shift, capslock:                    'D'
     ralt:                               '\u00f0'
-    shift+ralt:                         '\u00d0'
+    shift+ralt, capslock+ralt:          '\u00d0'
 }
 
 key F {
@@ -279,7 +279,7 @@
     base:                               'l'
     shift, capslock:                    'L'
     ralt:                               '\u00f8'
-    shift+ralt:                         '\u00d8'
+    shift+ralt, capslock+ralt:          '\u00d8'
 }
 
 key SEMICOLON {
@@ -313,7 +313,7 @@
     base:                               'z'
     shift, capslock:                    'Z'
     ralt:                               '\u00e6'
-    shift+ralt:                         '\u00c6'
+    shift+ralt, capslock+ralt:          '\u00c6'
 }
 
 key X {
@@ -347,7 +347,7 @@
     base:                               'n'
     shift, capslock:                    'N'
     ralt:                               '\u00f1'
-    shift+ralt:                         '\u00d1'
+    shift+ralt, capslock+ralt:          '\u00d1'
 }
 
 key M {
@@ -362,7 +362,7 @@
     base:                               ','
     shift:                              '<'
     ralt:                               '\u00e7'
-    shift+ralt:                         '\u00c7'
+    shift+ralt, capslock+ralt:          '\u00c7'
 }
 
 key PERIOD {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm b/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm
index 70c1fa4..2eb0f63 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 #
-# Slovak keyboard layout.
+# Slovak (EU - qwerty) keyboard layout.
 #
 
 type OVERLAY
@@ -26,94 +26,90 @@
     label:                              ';'
     base:                               ';'
     shift:                              '\u00b0'
-    ralt:                               '`'
-    ralt+shift:                         '~'
 }
 
 key 1 {
     label:                              '1'
     base:                               '+'
     shift:                              '1'
-    ralt:                               '!'
+    ralt:                               '~'
 }
 
 key 2 {
     label:                              '2'
     base:                               '\u013e'
     shift:                              '2'
-    ralt:                               '@'
+    ralt:                               '\u02c7'
 }
 
 key 3 {
     label:                              '3'
     base:                               '\u0161'
     shift:                              '3'
-    ralt:                               '#'
+    ralt:                               '\u0302'
 }
 
 key 4 {
     label:                              '4'
     base:                               '\u010d'
     shift:                              '4'
-    ralt:                               '$'
+    ralt:                               '\u02d8'
 }
 
 key 5 {
     label:                              '5'
     base:                               '\u0165'
     shift:                              '5'
-    ralt:                               '%'
+    ralt:                               '\u00b0'
 }
 
 key 6 {
     label:                              '6'
     base:                               '\u017e'
     shift:                              '6'
-    ralt:                               '^'
+    ralt:                               '\u02db'
 }
 
 key 7 {
     label:                              '7'
     base:                               '\u00fd'
     shift:                              '7'
-    ralt:                               '&'
+    ralt:                               '\u0300'
 }
 
 key 8 {
     label:                              '8'
     base:                               '\u00e1'
     shift:                              '8'
-    ralt:                               '*'
+    ralt:                               '\u02d9'
 }
 
 key 9 {
     label:                              '9'
     base:                               '\u00ed'
     shift:                              '9'
-    ralt:                               '('
+    ralt:                               '\u0301'
 }
 
 key 0 {
     label:                              '0'
     base:                               '\u00e9'
     shift:                              '0'
-    ralt:                               ')'
+    ralt:                               '\u02dd'
 }
 
 key MINUS {
     label:                              '='
     base:                               '='
     shift:                              '%'
-    ralt:                               '-'
-    ralt+shift:                         '_'
+    ralt:                               '\u0308'
 }
 
 key EQUALS {
     label:                              '\u00b4'
     base:                               '\u0301'
     shift:                              '\u030c'
-    ralt:                               '='
-    ralt+shift:                         '+'
+    ralt:                               '\u00b8'
 }
 
 ### ROW 2
@@ -179,22 +175,21 @@
     label:                              'P'
     base:                               'p'
     shift, capslock:                    'P'
+    ralt:                               '\''
 }
 
 key LEFT_BRACKET {
     label:                              '\u00fa'
     base:                               '\u00fa'
     shift:                              '/'
-    ralt:                               '['
-    ralt+shift:                         '{'
+    ralt:                               '\u00f7'
 }
 
 key RIGHT_BRACKET {
     label:                              '\u00e4'
     base:                               '\u00e4'
     shift:                              '('
-    ralt:                               ']'
-    ralt+shift:                         '}'
+    ralt:                               '\u00d7'
 }
 
 ### ROW 3
@@ -209,24 +204,28 @@
     label:                              'S'
     base:                               's'
     shift, capslock:                    'S'
+    ralt:                               '\u0111'
 }
 
 key D {
     label:                              'D'
     base:                               'd'
     shift, capslock:                    'D'
+    ralt:                               '\u0110'
 }
 
 key F {
     label:                              'F'
     base:                               'f'
     shift, capslock:                    'F'
+    ralt:                               '['
 }
 
 key G {
     label:                              'G'
     base:                               'g'
     shift, capslock:                    'G'
+    ralt:                               ']'
 }
 
 key H {
@@ -245,64 +244,65 @@
     label:                              'K'
     base:                               'k'
     shift, capslock:                    'K'
+    ralt:                               '\u0142'
 }
 
 key L {
     label:                              'L'
     base:                               'l'
     shift, capslock:                    'L'
+    ralt:                               '\u0141'
 }
 
 key SEMICOLON {
     label:                              '\u00f4'
     base:                               '\u00f4'
     shift:                              '"'
-    ralt:                               ';'
-    ralt+shift:                         ':'
+    ralt:                               '$'
 }
 
 key APOSTROPHE {
     label:                              '\u00a7'
     base:                               '\u00a7'
     shift:                              '!'
-    ralt:                               '\''
-    ralt+shift:                         '"'
+    ralt:                               '\u00df'
 }
 
 key BACKSLASH {
     label:                              '\u0148'
     base:                               '\u0148'
     shift:                              ')'
-    ralt:                               '\\'
-    ralt+shift:                         '|'
+    ralt:                               '\u00a4'
 }
 
 ### ROW 4
 
 key PLUS {
-    label:                              '\\'
-    base:                               '\\'
-    shift:                              '|'
-    ralt:                               '&'
-    ralt+shift:                         '*'
+    label:                              '&'
+    base:                               '&'
+    shift:                              '*'
+    ralt:                               '<'
 }
 
 key Z {
     label:                              'Z'
     base:                               'z'
     shift, capslock:                    'Z'
+    ralt:                               '>'
 }
 
 key X {
     label:                              'X'
     base:                               'x'
     shift, capslock:                    'X'
+    ralt:                               '#'
 }
 
 key C {
     label:                              'C'
     base:                               'c'
     shift, capslock:                    'C'
+    ralt:                               '&'
 }
 
 key V {
@@ -316,12 +316,14 @@
     label:                              'B'
     base:                               'b'
     shift, capslock:                    'B'
+    ralt:                               '{'
 }
 
 key N {
     label:                              'N'
     base:                               'n'
     shift, capslock:                    'N'
+    ralt:                               '}'
 }
 
 key M {
@@ -348,6 +350,5 @@
     label:                              '-'
     base:                               '-'
     shift:                              '_'
-    ralt:                               '/'
-    ralt+shift:                         '?'
+    ralt:                               '*'
 }
diff --git a/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm b/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm
index a75d154..9e20462 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm
@@ -56,12 +56,14 @@
     label:                              '4'
     base:                               '4'
     shift:                              '\u00e7'
+    ralt:                               '\u00b0'
 }
 
 key 5 {
     label:                              '5'
     base:                               '5'
     shift:                              '%'
+    ralt:                               '\u00a7'
 }
 
 key 6 {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm b/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm
index ae93f4b..7fbd1a9 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm
@@ -56,12 +56,14 @@
     label:                              '4'
     base:                               '4'
     shift:                              '\u00e7'
+    ralt:                               '\u00b0'
 }
 
 key 5 {
     label:                              '5'
     base:                               '5'
     shift:                              '%'
+    ralt:                               '\u00a7'
 }
 
 key 6 {
@@ -178,6 +180,8 @@
     label:                              '\u00fc'
     base:                               '\u00fc'
     shift:                              '\u00e8'
+    capslock:                           '\u00dc'
+    capslock+shift:                     '\u00c8'
     ralt:                               '['
 }
 
@@ -248,12 +252,16 @@
     label:                              '\u00f6'
     base:                               '\u00f6'
     shift:                              '\u00e9'
+    capslock:                           '\u00d6'
+    capslock+shift:                     '\u00c9'
 }
 
 key APOSTROPHE {
     label:                              '\u00e4'
     base:                               '\u00e4'
     shift:                              '\u00e0'
+    capslock:                           '\u00c4'
+    capslock+shift:                     '\u00c0'
     ralt:                               '{'
 }
 
diff --git a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
index 0e2b33a..e167817 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
@@ -92,7 +92,7 @@
            >
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key1"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -101,7 +101,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key2"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -110,7 +110,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key3"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -126,7 +126,7 @@
            >
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key4"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -135,7 +135,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key5"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -144,7 +144,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key6"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -160,7 +160,7 @@
            >
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key7"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -169,7 +169,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key8"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -178,7 +178,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key9"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -199,7 +199,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key0"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -208,7 +208,7 @@
                />
            <ImageButton
                android:id="@+id/key_enter"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
diff --git a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
index 88049a7..ac798ca 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
@@ -93,7 +93,7 @@
            >
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key1"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -102,7 +102,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key2"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -111,7 +111,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key3"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -127,7 +127,7 @@
            >
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key4"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -136,7 +136,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key5"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -145,7 +145,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key6"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -161,7 +161,7 @@
            >
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key7"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -170,7 +170,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key8"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -179,7 +179,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key9"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -200,7 +200,7 @@
                />
            <view class="com.android.keyguard.NumPadKey"
                android:id="@+id/key0"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
@@ -209,7 +209,7 @@
                />
            <ImageButton
                android:id="@+id/key_enter"
-               style="@style/Widget.Button.NumPadKey"
+               style="@style/Widget.Button.NumPadKey.Sim"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml
index 3b3a069..546ddd4 100644
--- a/packages/Keyguard/res/layout/keyguard_status_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_view.xml
@@ -24,7 +24,7 @@
     android:id="@+id/keyguard_status_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_height="wrap_content"
     androidprv:layout_maxWidth="@dimen/keyguard_security_width"
     androidprv:layout_maxHeight="@dimen/keyguard_security_height"
     android:gravity="center_horizontal|top"
diff --git a/packages/Keyguard/res/values-sw600dp/dimens.xml b/packages/Keyguard/res/values-sw600dp/dimens.xml
index ea5ef27..25e86e1 100644
--- a/packages/Keyguard/res/values-sw600dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw600dp/dimens.xml
@@ -32,7 +32,7 @@
 
     <!-- Keyguard dimensions -->
     <!-- Size of the clock font in keyguard's status view -->
-    <dimen name="kg_status_clock_font_size">141dp</dimen>
+    <dimen name="kg_status_clock_font_size">120dp</dimen>
 
     <!-- Size of the generic status lines keyguard's status view  -->
     <dimen name="kg_status_line_font_size">16sp</dimen>
diff --git a/packages/Keyguard/res/values-sw720dp/dimens.xml b/packages/Keyguard/res/values-sw720dp/dimens.xml
index 4853a7b..30b979c 100644
--- a/packages/Keyguard/res/values-sw720dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw720dp/dimens.xml
@@ -19,7 +19,7 @@
 <resources>
     <!-- Keyguard dimensions -->
     <!-- Size of the clock font in keyguard's status view -->
-    <dimen name="kg_status_clock_font_size">188dp</dimen>
+    <dimen name="kg_status_clock_font_size">140dp</dimen>
 
     <!-- Size of the generic status lines keyguard's status view  -->
     <dimen name="kg_status_line_font_size">19sp</dimen>
diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml
index b54ac50..5ab00d2 100644
--- a/packages/Keyguard/res/values/styles.xml
+++ b/packages/Keyguard/res/values/styles.xml
@@ -33,6 +33,10 @@
         <item name="android:paddingLeft">20dp</item>
         <item name="android:paddingRight">6dp</item>
     </style>
+    <style name="Widget.Button.NumPadKey.Sim" >
+        <item name="android:paddingTop">3dp</item>
+        <item name="android:paddingBottom">4dp</item>
+    </style>
     <style name="TextAppearance.NumPadKey"
             parent="@android:style/TextAppearance">
         <item name="android:textSize">34dp</item>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 862931e..7be4cec 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -168,9 +168,9 @@
 
     /**
      * Called when the screen turns off
-     * @param why {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
-     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
-     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
+     * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_ADMIN},
+     * {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER}, or
+     * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT}.
      */
     public void onScreenTurnedOff(int why) { }
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 327df8d..6b62c25 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -98,6 +98,9 @@
     <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
     <uses-permission android:name="android.permission.TRUST_LISTENER" />
 
+    <!-- Recents -->
+    <uses-permission android:name="android.permission.BIND_APPWIDGET" />
+
     <!-- Wifi Display -->
     <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
 
@@ -138,7 +141,7 @@
                 android:exported="true" />
 
         <receiver android:name=".BootReceiver" androidprv:primaryUserOnly="true">
-            <intent-filter>
+            <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_ime_switcher_default.png b/packages/SystemUI/res/drawable-hdpi/ic_ime_switcher_default.png
new file mode 100644
index 0000000..369c88d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_ime_switcher_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_ime_switcher_default.png b/packages/SystemUI/res/drawable-mdpi/ic_ime_switcher_default.png
new file mode 100644
index 0000000..7d97eb5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_ime_switcher_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_ime_switcher_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_ime_switcher_default.png
new file mode 100644
index 0000000..900801a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_ime_switcher_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_ime_switcher_default.png b/packages/SystemUI/res/drawable-xxhdpi/ic_ime_switcher_default.png
new file mode 100644
index 0000000..6c8222e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_ime_switcher_default.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
index aa7256b..5f12706 100644
--- a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
@@ -43,7 +43,7 @@
 
             <!-- navigation controls -->
             <View
-                android:layout_width="40dp"
+                android:layout_width="@dimen/navigation_extra_key_width"
                 android:layout_height="match_parent"
                 android:layout_weight="0"
                 android:visibility="invisible"
@@ -88,16 +88,29 @@
                 systemui:glowBackground="@drawable/ic_sysbar_highlight"
                 android:contentDescription="@string/accessibility_recent"
                 />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="@dimen/navigation_menu_key_width"
+            <FrameLayout
+                android:layout_width="@dimen/navigation_extra_key_width"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_menu"
-                systemui:keyCode="82"
-                android:layout_weight="0"
-                android:visibility="invisible"
-                android:contentDescription="@string/accessibility_menu"
-                systemui:glowBackground="@drawable/ic_sysbar_highlight"
-                />
+                android:layout_weight="0" >
+                <com.android.systemui.statusbar.policy.KeyButtonView
+                    android:id="@+id/menu"
+                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_height="match_parent"
+                    android:contentDescription="@string/accessibility_menu"
+                    android:src="@drawable/ic_sysbar_menu"
+                    android:visibility="invisible"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                    systemui:keyCode="82" />
+                <com.android.systemui.statusbar.policy.KeyButtonView
+                    android:id="@+id/ime_switcher"
+                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_height="match_parent"
+                    android:contentDescription="@string/accessibility_ime_switch_button"
+                    android:scaleType="centerInside"
+                    android:src="@drawable/ic_ime_switcher_default"
+                    android:visibility="invisible"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight" />
+            </FrameLayout>
         </LinearLayout>
 
         <!-- lights out layout to match exactly -->
@@ -187,16 +200,29 @@
             >
             
             <!-- navigation controls -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_height="40dp"
-                android:layout_width="match_parent"
-                android:src="@drawable/ic_sysbar_menu_land"
-                systemui:keyCode="82"
-                android:layout_weight="0"
-                android:visibility="invisible"
-                android:contentDescription="@string/accessibility_menu"
-                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
-                />
+            <FrameLayout
+                android:layout_width="@dimen/navigation_extra_key_width"
+                android:layout_height="match_parent"
+                android:layout_weight="0" >
+                <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                    android:layout_height="@dimen/navigation_extra_key_width"
+                    android:layout_width="match_parent"
+                    android:src="@drawable/ic_sysbar_menu_land"
+                    systemui:keyCode="82"
+                    android:layout_weight="0"
+                    android:visibility="invisible"
+                    android:contentDescription="@string/accessibility_menu"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight_land" />
+                <com.android.systemui.statusbar.policy.KeyButtonView
+                    android:id="@+id/ime_switcher"
+                    android:layout_height="@dimen/navigation_extra_key_width"
+                    android:layout_width="match_parent"
+                    android:contentDescription="@string/accessibility_ime_switch_button"
+                    android:scaleType="centerInside"
+                    android:src="@drawable/ic_ime_switcher_default"
+                    android:visibility="invisible"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight" />
+            </FrameLayout>
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
                 android:layout_height="80dp"
                 android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index b9ad799..6a2e3c6 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -42,7 +42,7 @@
 
             <!-- navigation controls -->
             <View
-                android:layout_width="48dp"
+                android:layout_width="@dimen/navigation_extra_key_width"
                 android:layout_height="match_parent"
                 android:layout_weight="0"
                 android:layout_marginStart="2dp"
@@ -85,17 +85,32 @@
                 android:layout_height="match_parent"
                 android:layout_weight="1"
                 />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="48dp"
+            <FrameLayout
+                android:layout_width="@dimen/navigation_extra_key_width"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_menu"
-                android:layout_marginEnd="2dp"
-                systemui:keyCode="82"
                 android:layout_weight="0"
-                android:visibility="invisible"
-                android:contentDescription="@string/accessibility_menu"
-                systemui:glowBackground="@drawable/ic_sysbar_highlight"
-                />
+                android:layout_marginEnd="2dp" >
+                <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_height="match_parent"
+                    android:src="@drawable/ic_sysbar_menu"
+                    android:layout_marginEnd="2dp"
+                    systemui:keyCode="82"
+                    android:visibility="invisible"
+                    android:contentDescription="@string/accessibility_menu"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                    />
+                <com.android.systemui.statusbar.policy.KeyButtonView
+                    android:id="@+id/ime_switcher"
+                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_height="match_parent"
+                    android:layout_marginEnd="2dp"
+                    android:scaleType="centerInside"
+                    android:src="@drawable/ic_ime_switcher_default"
+                    android:visibility="invisible"
+                    android:contentDescription="@string/accessibility_ime_switch_button"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight" />
+            </FrameLayout>
         </LinearLayout>
 
         <!-- lights out layout to match exactly -->
@@ -184,7 +199,7 @@
 
             <!-- navigation controls -->
             <View
-                android:layout_width="48dp"
+                android:layout_width="@dimen/navigation_extra_key_width"
                 android:layout_height="match_parent"
                 android:layout_weight="0"
                 android:layout_marginStart="2dp"
@@ -227,17 +242,32 @@
                 android:layout_height="match_parent"
                 android:layout_weight="1"
                 />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="48dp"
+            <FrameLayout
+                android:layout_width="@dimen/navigation_extra_key_width"
                 android:layout_height="match_parent"
                 android:layout_marginEnd="2dp"
-                android:src="@drawable/ic_sysbar_menu"
-                systemui:keyCode="82"
-                android:layout_weight="0"
-                android:visibility="invisible"
-                android:contentDescription="@string/accessibility_menu"
-                systemui:glowBackground="@drawable/ic_sysbar_highlight"
-                />
+                android:layout_weight="0" >
+                <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_height="match_parent"
+                    android:layout_marginEnd="2dp"
+                    android:src="@drawable/ic_sysbar_menu"
+                    systemui:keyCode="82"
+                    android:visibility="invisible"
+                    android:contentDescription="@string/accessibility_menu"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                    />
+                <com.android.systemui.statusbar.policy.KeyButtonView
+                    android:id="@+id/ime_switcher"
+                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_height="match_parent"
+                    android:layout_marginEnd="2dp"
+                    android:src="@drawable/ic_ime_switcher_default"
+                    android:visibility="invisible"
+                    android:contentDescription="@string/accessibility_ime_switch_button"
+                    android:scaleType="centerInside"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight" />
+            </FrameLayout>
         </LinearLayout>
 
         <!-- lights out layout to match exactly -->
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 2398849..7470409 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -88,16 +88,31 @@
                 systemui:glowBackground="@drawable/ic_sysbar_highlight"
                 android:contentDescription="@string/accessibility_recent"
                 />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="@dimen/navigation_menu_key_width"
+            <FrameLayout
+                android:layout_width="@dimen/navigation_extra_key_width"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_menu"
-                systemui:keyCode="82"
-                android:layout_weight="0"
-                android:visibility="invisible"
-                android:contentDescription="@string/accessibility_menu"
-                systemui:glowBackground="@drawable/ic_sysbar_highlight"
-                />
+                android:layout_weight="0" >
+                <com.android.systemui.statusbar.policy.KeyButtonView
+                    android:id="@+id/menu"
+                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_height="match_parent"
+                    android:contentDescription="@string/accessibility_menu"
+                    android:src="@drawable/ic_sysbar_menu"
+                    android:visibility="invisible"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                    systemui:keyCode="82" />
+
+                <com.android.systemui.statusbar.policy.KeyButtonView
+                    android:id="@+id/ime_switcher"
+                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_height="match_parent"
+                    android:contentDescription="@string/accessibility_ime_switch_button"
+                    android:scaleType="centerInside"
+                    android:src="@drawable/ic_ime_switcher_default"
+                    android:visibility="invisible"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight" />
+            </FrameLayout>
+
         </LinearLayout>
 
         <!-- lights out layout to match exactly -->
@@ -190,18 +205,33 @@
             android:id="@+id/nav_buttons"
             android:animateLayoutChanges="true"
             >
-            
+
             <!-- navigation controls -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_height="40dp"
-                android:layout_width="match_parent"
-                android:src="@drawable/ic_sysbar_menu_land"
-                systemui:keyCode="82"
+            <FrameLayout
                 android:layout_weight="0"
-                android:visibility="invisible"
-                android:contentDescription="@string/accessibility_menu"
-                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
-                />
+                android:layout_width="match_parent"
+                android:layout_height="40dp" >
+                <com.android.systemui.statusbar.policy.KeyButtonView
+                    android:id="@+id/ime_switcher"
+                    android:layout_width="match_parent"
+                    android:layout_height="40dp"
+                    android:contentDescription="@string/accessibility_ime_switch_button"
+                    android:scaleType="centerInside"
+                    android:src="@drawable/ic_ime_switcher_default"
+                    android:visibility="invisible"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight" />
+
+                <com.android.systemui.statusbar.policy.KeyButtonView
+                    android:id="@+id/menu"
+                    android:layout_width="match_parent"
+                    android:layout_height="40dp"
+                    android:contentDescription="@string/accessibility_menu"
+                    android:src="@drawable/ic_sysbar_menu_land"
+                    android:visibility="invisible"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+                    systemui:keyCode="82" />
+            </FrameLayout>
+
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
                 android:layout_height="80dp"
                 android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
deleted file mode 100644
index 15d0890..0000000
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index ddc0dbf..f7df18eb 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -58,7 +58,7 @@
             android:textSize="22sp"
             android:textColor="#ffffffff"
             android:text="@string/recents_empty_message"
-            android:fontFamily="sans-serif-thin"
+            android:fontFamily="sans-serif-light"
             android:singleLine="true"
             android:maxLines="2"
             android:ellipsize="marquee"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 24ccb2b..761ad42 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -54,51 +54,45 @@
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium" />
 
-    <LinearLayout
+    <include layout="@layout/status_bar_expanded_header"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/notification_panel_header_height"
+        />
+
+    <include
+        layout="@layout/keyguard_status_view"
+        android:layout_height="wrap_content"
+        android:visibility="gone" />
+
+    <TextView
+        android:id="@+id/emergency_calls_only"
+        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:padding="4dp"
+        android:gravity="center"
+        android:visibility="gone"
+        />
+
+    <FrameLayout
+        android:id="@+id/notification_container_parent"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/close_handle_underlap"
-        android:orientation="vertical"
-        android:animateLayoutChanges="false"
         >
-
-        <include layout="@layout/status_bar_expanded_header"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/notification_panel_header_height"
-            />
-
         <include
-            layout="@layout/keyguard_status_view"
-            android:visibility="gone" />
-
-        <TextView
-            android:id="@+id/emergency_calls_only"
-            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
-            android:layout_height="wrap_content"
+            layout="@layout/flip_settings"
+            android:layout_marginTop="@dimen/notification_panel_header_height"
             android:layout_width="match_parent"
-            android:padding="4dp"
-            android:gravity="center"
-            android:visibility="gone"
+            android:layout_height="wrap_content"
             />
 
-        <FrameLayout
-            android:id="@+id/notification_container_parent"
+        <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+            android:id="@+id/notification_stack_scroller"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            >
-            <include
-                layout="@layout/flip_settings"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                />
-
-            <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
-                    android:id="@+id/notification_stack_scroller"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    />
-        </FrameLayout>
-    </LinearLayout>
+            />
+    </FrameLayout>
 
     <include
         layout="@layout/keyguard_bottom_area"
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 3c4e0d3..451476c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -222,6 +222,6 @@
   <plurals name="keyguard_more_overflow_text">
     <item quantity="other" msgid="9180696159506883684">"%d mehr"</item>
   </plurals>
-    <string name="notification_tap_again" msgid="7590196980943943842">"Zum Öffnen erneut tippen"</string>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Erneut tippen, um Benachrichtigung zu öffnen"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Zum Entsperren nach oben wischen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 0e9f5b7..379cfce 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -69,7 +69,7 @@
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nepavyko užfiksuoti ekrano kopijos."</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"Nepavyko išsaugoti ekrano kopijos. Gali būti naudojama atmintis."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
-    <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvą (MTP)"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvę (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Įmontuoti kaip fotoaparatą (PTP)"</string>
     <string name="installer_cd_button_title" msgid="2312667578562201583">"Įdiegti „Mac“ skirtą „Android“ perkėl. priem. pr."</string>
     <string name="accessibility_back" msgid="567011538994429120">"Atgal"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index aa7e6eb..587b84f 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -220,8 +220,6 @@
   <plurals name="keyguard_more_overflow_text">
     <item quantity="other" msgid="9180696159506883684">"%d lagi"</item>
   </plurals>
-    <!-- no translation found for notification_tap_again (7590196980943943842) -->
-    <skip />
-    <!-- no translation found for keyguard_unlock (8043466894212841998) -->
-    <skip />
+    <string name="notification_tap_again" msgid="7590196980943943842">"Ketik lagi untuk membuka"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Leret ke atas untuk membuka kunci"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 6281110..5c9764a 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -220,8 +220,6 @@
   <plurals name="keyguard_more_overflow_text">
     <item quantity="other" msgid="9180696159506883684">"Încă %d"</item>
   </plurals>
-    <!-- no translation found for notification_tap_again (7590196980943943842) -->
-    <skip />
-    <!-- no translation found for keyguard_unlock (8043466894212841998) -->
-    <skip />
+    <string name="notification_tap_again" msgid="7590196980943943842">"Atingeți din nou pentru a deschide"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Glisați în sus pentru a debloca"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 5b5587d..92e3885 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -36,6 +36,9 @@
     <!-- Height of search panel including navigation bar height -->
     <dimen name="navbar_search_panel_height">280dip</dimen>
 
+    <!-- The width of the view containing the menu/ime navigation bar icons -->
+    <dimen name="navigation_extra_key_width">48dip</dimen>
+
     <!-- Size of application thumbnail -->
     <dimen name="status_bar_recents_thumbnail_width">200dp</dimen>
     <dimen name="status_bar_recents_thumbnail_height">177dp</dimen>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 722ca15..024f1eb 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -115,8 +115,10 @@
     <integer name="recents_filter_animate_current_views_min_duration">175</integer>
     <!-- The min animation duration for animating views that are newly visible. -->
     <integer name="recents_filter_animate_new_views_min_duration">125</integer>
-    <!-- The min animation duration for animating views that are newly visible. -->
+    <!-- The min animation duration for animating the task bar in. -->
     <integer name="recents_animate_task_bar_enter_duration">200</integer>
+    <!-- The min animation duration for animating the task bar out. -->
+    <integer name="recents_animate_task_bar_exit_duration">150</integer>
     <!-- The animation duration for animating in the info pane. -->
     <integer name="recents_animate_task_view_info_pane_duration">150</integer>
     <!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 0fac8c0..1900fea 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -128,8 +128,8 @@
     <!-- The width of the view containing non-menu status bar icons -->
     <dimen name="navigation_key_width">80dip</dimen>
 
-    <!-- The width of the view containing the menu status bar icon -->
-    <dimen name="navigation_menu_key_width">40dip</dimen>
+    <!-- The width of the view containing the menu/ime navigation bar icons -->
+    <dimen name="navigation_extra_key_width">40dip</dimen>
 
     <!-- Default distance beyond which snaps to the matching target -->
     <dimen name="navbar_search_snap_margin">40dip</dimen>
@@ -231,10 +231,7 @@
     <dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
 
     <!-- The height of the search bar space. -->
-    <dimen name="recents_search_bar_space_height">40dp</dimen>
-
-    <!-- The search bar edge margins. -->
-    <dimen name="recents_search_bar_space_edge_margins">12dp</dimen>
+    <dimen name="recents_search_bar_space_height">64dp</dimen>
 
     <!-- Used to calculate the translation animation duration, the expected amount of movement 
          in dps over one second of time. -->
@@ -266,4 +263,9 @@
 
     <dimen name="quick_settings_tmp_scrim_stroke_width">8dp</dimen>
     <dimen name="quick_settings_tmp_scrim_text_size">30dp</dimen>
+
+    <dimen name="notifications_top_padding">8dp</dimen>
+    
+    <!-- Minimum distance the user has to drag down to go to the full shade. -->
+    <dimen name="keyguard_drag_down_min_distance">100dp</dimen>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 61c268e..4d6d815c 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -29,17 +29,16 @@
 import android.view.ScaleGestureDetector;
 import android.view.ScaleGestureDetector.OnScaleGestureListener;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewConfiguration;
 
-import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 
-public class ExpandHelper implements Gefingerpoken, OnClickListener {
+public class ExpandHelper implements Gefingerpoken {
     public interface Callback {
-        View getChildAtRawPosition(float x, float y);
-        View getChildAtPosition(float x, float y);
+        ExpandableView getChildAtRawPosition(float x, float y);
+        ExpandableView getChildAtPosition(float x, float y);
         boolean canChildBeExpanded(View v);
         void setUserExpandedChild(View v, boolean userExpanded);
         void setUserLockedChild(View v, boolean userLocked);
@@ -48,9 +47,7 @@
     private static final String TAG = "ExpandHelper";
     protected static final boolean DEBUG = false;
     protected static final boolean DEBUG_SCALE = false;
-    protected static final boolean DEBUG_GLOW = false;
     private static final long EXPAND_DURATION = 250;
-    private static final long GLOW_DURATION = 150;
 
     // Set to false to disable focus-based gestures (spread-finger vertical pull).
     private static final boolean USE_DRAG = true;
@@ -115,7 +112,7 @@
             float focusX = detector.getFocusX();
             float focusY = detector.getFocusY();
 
-            final View underFocus = findView(focusX, focusY);
+            final ExpandableView underFocus = findView(focusX, focusY);
             startExpanding(underFocus, STRETCH);
             return mExpanding;
         }
@@ -172,24 +169,6 @@
         mPopDuration = mContext.getResources().getInteger(R.integer.blinds_pop_duration_ms);
         mPullGestureMinXSpan = mContext.getResources().getDimension(R.dimen.pull_span_min);
 
-        AnimatorListenerAdapter glowVisibilityController = new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                View target = (View) ((ObjectAnimator) animation).getTarget();
-                if (target.getAlpha() <= 0.0f) {
-                    target.setVisibility(View.VISIBLE);
-                }
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                View target = (View) ((ObjectAnimator) animation).getTarget();
-                if (target.getAlpha() <= 0.0f) {
-                    target.setVisibility(View.INVISIBLE);
-                }
-            }
-        };
-
         final ViewConfiguration configuration = ViewConfiguration.get(mContext);
         mTouchSlop = configuration.getScaledTouchSlop();
 
@@ -221,8 +200,8 @@
         return out;
     }
 
-    private View findView(float x, float y) {
-        View v = null;
+    private ExpandableView findView(float x, float y) {
+        ExpandableView v;
         if (mEventSource != null) {
             int[] location = new int[2];
             mEventSource.getLocationOnScreen(location);
@@ -271,15 +250,6 @@
         mScrollAdapter = adapter;
     }
 
-    private float calculateGlow(float target, float actual) {
-        // glow if overscale
-        if (DEBUG_GLOW) Log.d(TAG, "target: " + target + " actual: " + actual);
-        float stretch = Math.abs((target - actual) / mMaximumStretch);
-        float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
-        if (DEBUG_GLOW) Log.d(TAG, "stretch: " + stretch + " strength: " + strength);
-        return (GLOW_BASE + strength * (1f - GLOW_BASE));
-    }
-
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         final int action = ev.getAction();
@@ -313,7 +283,7 @@
                 // detect a vertical pulling gesture with fingers somewhat separated
                 if (DEBUG_SCALE) Log.v(TAG, "got pull gesture (xspan=" + xspan + "px)");
 
-                final View underFocus = findView(x, y);
+                final ExpandableView underFocus = findView(x, y);
                 startExpanding(underFocus, PULL);
                 return true;
             }
@@ -328,7 +298,7 @@
                     if (yDiff > mTouchSlop) {
                         if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
                         mLastMotionY = y;
-                        final View underFocus = findView(x, y);
+                        final ExpandableView underFocus = findView(x, y);
                         if (startExpanding(underFocus, BLINDS)) {
                             mInitialTouchY = mLastMotionY;
                             mHasPopped = false;
@@ -394,7 +364,7 @@
 
                     final int x = (int) mSGD.getFocusX();
                     final int y = (int) mSGD.getFocusY();
-                    View underFocus = findView(x, y);
+                    ExpandableView underFocus = findView(x, y);
                     if (isFinished && underFocus != null && underFocus != mCurrView) {
                         finishExpanding(false); // @@@ needed?
                         startExpanding(underFocus, BLINDS);
@@ -432,7 +402,7 @@
     /**
      * @return True if the view is expandable, false otherwise.
      */
-    private boolean startExpanding(View v, int expandType) {
+    private boolean startExpanding(ExpandableView v, int expandType) {
         if (!(v instanceof ExpandableNotificationRow)) {
             return false;
         }
@@ -512,13 +482,6 @@
         mCurrView = v;
     }
 
-    @Override
-    public void onClick(View v) {
-        startExpanding(v, STRETCH);
-        finishExpanding(true);
-        clearView();
-    }
-
     /**
      * Use this to abort any pending expansions in progress.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 74483cc..4857adc 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -211,6 +211,7 @@
             if (mReceiver != null) {
                 unregisterReceiver(mReceiver);
             }
+            mBackground = null;
         }
 
         void updateSurfaceSize(SurfaceHolder surfaceHolder) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 103991a..217074f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -65,6 +65,8 @@
         // the theme set there.
         setTheme(R.style.systemui_theme);
 
+        IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
@@ -80,7 +82,7 @@
                     }
                 }
             }
-        }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+        }, filter);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index ffdb620..f812e8c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -542,9 +542,8 @@
 
     /**
      * Called to let us know the screen was turned off.
-     * @param why either {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_USER},
-     *   {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
-     *   {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
+     * @param why either {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_USER} or
+     *   {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT}.
      */
     public void onScreenTurnedOff(int why) {
         synchronized (this) {
@@ -576,8 +575,6 @@
             } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
                    || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
                 doKeyguardLaterLocked();
-            } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
-                // Do not enable the keyguard if the prox sensor forced the screen off.
             } else {
                 doKeyguardLocked(null);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index 4b75c99..c8d97cc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -37,7 +37,7 @@
     public static final String AnsiRed = "\u001B[31m";      // SystemUIHandshake
     public static final String AnsiGreen = "\u001B[32m";    // MeasureAndLayout
     public static final String AnsiYellow = "\u001B[33m";   // SynchronizeViewsWithModel
-    public static final String AnsiBlue = "\u001B[34m";     // TouchEvents
+    public static final String AnsiBlue = "\u001B[34m";     // TouchEvents, Search
     public static final String AnsiPurple = "\u001B[35m";   // Draw
     public static final String AnsiCyan = "\u001B[36m";     // ClickEvents
     public static final String AnsiWhite = "\u001B[37m";
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 72d9a52..bc8ab45 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -26,10 +26,11 @@
         public static final boolean Verbose = false;
 
         public static class App {
-            public static final boolean EnableTaskFiltering = true;
+            public static final boolean EnableTaskFiltering = false;
             public static final boolean EnableTaskStackClipping = false;
+            public static final boolean EnableTaskBarThemeColors = true;
             public static final boolean EnableInfoPane = true;
-            public static final boolean EnableSearchButton = false;
+            public static final boolean EnableSearchButton = true;
 
             // This disables the bitmap and icon caches
             public static final boolean DisableBackgroundCache = false;
@@ -51,6 +52,7 @@
             public static final boolean SystemUIHandshake = false;
             public static final boolean TimeSystemCalls = false;
             public static final boolean Memory = false;
+            public static final boolean Search = false;
         }
 
         public static class UI {
@@ -71,6 +73,10 @@
     }
 
     public static class Values {
+        public static class App {
+            public static int AppWidgetHostId = 1024;
+            public static String Key_SearchAppWidgetId = "searchAppWidgetId";
+        }
         public static class Window {
             // The dark background dim is set behind the empty recents view
             public static final float DarkBackgroundDim = 0.5f;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 71c45f2..110130b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -17,11 +17,17 @@
 package com.android.systemui.recents;
 
 import android.app.Activity;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.SharedPreferences;
 import android.os.Bundle;
+import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
@@ -33,13 +39,37 @@
 
 import java.util.ArrayList;
 
+/** Our special app widget host */
+class RecentsAppWidgetHost extends AppWidgetHost {
+    /* Callbacks to notify when an app package changes */
+    interface RecentsAppWidgetHostCallbacks {
+        public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo);
+    }
+
+    RecentsAppWidgetHostCallbacks mCb;
+
+    public RecentsAppWidgetHost(Context context, int hostId, RecentsAppWidgetHostCallbacks cb) {
+        super(context, hostId);
+        mCb = cb;
+    }
+
+    @Override
+    protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) {
+        mCb.onProviderChanged(appWidgetId, appWidget);
+    }
+}
 
 /* Activity */
-public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks {
+public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
+        RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks{
     FrameLayout mContainerView;
     RecentsView mRecentsView;
     View mEmptyView;
 
+    AppWidgetHost mAppWidgetHost;
+    AppWidgetProviderInfo mSearchAppWidgetInfo;
+    AppWidgetHostView mSearchAppWidgetHostView;
+
     boolean mVisible;
     boolean mTaskLaunched;
 
@@ -102,6 +132,75 @@
         }
     }
 
+    /** Attempts to allocate and bind the search bar app widget */
+    void bindSearchBarAppWidget() {
+        if (Constants.DebugFlags.App.EnableSearchButton) {
+            RecentsConfiguration config = RecentsConfiguration.getInstance();
+            SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+
+            // Reset the host view and widget info
+            mSearchAppWidgetHostView = null;
+            mSearchAppWidgetInfo = null;
+
+            // Try and load the app widget id from the settings
+            int appWidgetId = config.searchBarAppWidgetId;
+            if (appWidgetId >= 0) {
+                mSearchAppWidgetInfo = ssp.getAppWidgetInfo(appWidgetId);
+                if (mSearchAppWidgetInfo == null) {
+                    // If there is no actual widget associated with that id, then delete it and
+                    // prepare to bind another app widget in its place
+                    ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
+                    appWidgetId = -1;
+                }
+                Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                        "[RecentsActivity|onCreate|settings|appWidgetId]",
+                        "Id: " + appWidgetId,
+                        Console.AnsiBlue);
+            }
+
+            // If there is no id, then bind a new search app widget
+            if (appWidgetId < 0) {
+                Pair<Integer, AppWidgetProviderInfo> widgetInfo =
+                        ssp.bindSearchAppWidget(mAppWidgetHost);
+                if (widgetInfo != null) {
+                    Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                            "[RecentsActivity|onCreate|searchWidget]",
+                            "Id: " + widgetInfo.first + " Info: " + widgetInfo.second,
+                            Console.AnsiBlue);
+
+                    // Save the app widget id into the settings
+                    config.updateSearchBarAppWidgetId(this, widgetInfo.first);
+                    mSearchAppWidgetInfo = widgetInfo.second;
+                }
+            }
+        }
+    }
+
+    /** Creates the search bar app widget view */
+    void addSearchBarAppWidgetView() {
+        if (Constants.DebugFlags.App.EnableSearchButton) {
+            RecentsConfiguration config = RecentsConfiguration.getInstance();
+            int appWidgetId = config.searchBarAppWidgetId;
+            if (appWidgetId >= 0) {
+                Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                        "[RecentsActivity|onCreate|addSearchAppWidgetView]",
+                        "Id: " + appWidgetId,
+                        Console.AnsiBlue);
+                mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
+                        mSearchAppWidgetInfo);
+                Bundle opts = new Bundle();
+                opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+                        AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+                mSearchAppWidgetHostView.updateAppWidgetOptions(opts);
+                // Set the padding to 0 for this search widget
+                mSearchAppWidgetHostView.setPadding(0, 0, 0, 0);
+                mRecentsView.setSearchBar(mSearchAppWidgetHostView);
+            } else {
+                mRecentsView.setSearchBar(null);
+            }
+        }
+    }
+
     /** Dismisses recents if we are already visible and the intent is to toggle the recents view */
     boolean dismissRecentsIfVisible() {
         if (mVisible) {
@@ -127,6 +226,9 @@
         RecentsTaskLoader.initialize(this);
         RecentsConfiguration.reinitialize(this);
 
+        // Initialize the widget host (the host id is static and does not change)
+        mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId, this);
+
         // Create the view hierarchy
         mRecentsView = new RecentsView(this);
         mRecentsView.setCallbacks(this);
@@ -145,6 +247,11 @@
 
         // Update the recent tasks
         updateRecentsTasks(getIntent());
+
+        // Bind the search app widget when we first start up
+        bindSearchBarAppWidget();
+        // Add the search bar layout
+        addSearchBarAppWidgetView();
     }
 
     @Override
@@ -165,6 +272,9 @@
 
         // Update the recent tasks
         updateRecentsTasks(intent);
+
+        // Don't attempt to rebind the search bar widget, but just add the search bar layout
+        addSearchBarAppWidgetView();
     }
 
     @Override
@@ -172,6 +282,7 @@
         Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsActivity|onStart]", "",
                 Console.AnsiRed);
         super.onStart();
+        mAppWidgetHost.startListening();
         mVisible = true;
     }
 
@@ -225,6 +336,7 @@
                 Console.AnsiRed);
         super.onStop();
 
+        mAppWidgetHost.stopListening();
         mVisible = false;
         mTaskLaunched = false;
     }
@@ -265,4 +377,18 @@
     public void onTaskLaunching() {
         mTaskLaunched = true;
     }
+
+    @Override
+    public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+        if (appWidgetId > -1 && appWidgetId == config.searchBarAppWidgetId) {
+            // The search provider may have changed, so just delete the old widget and bind it again
+            ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
+            config.updateSearchBarAppWidgetId(this, -1);
+            // Load the widget again
+            bindSearchBarAppWidget();
+            addSearchBarAppWidgetView();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index d54df13..5a1dc8d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
@@ -35,17 +36,25 @@
     public Rect systemInsets = new Rect();
     public Rect displayRect = new Rect();
 
+    boolean isLandscape;
+    int searchBarAppWidgetId = -1;
+
     public float animationPxMovementPerSecond;
 
     public int filteringCurrentViewsMinAnimDuration;
     public int filteringNewViewsMinAnimDuration;
     public int taskBarEnterAnimDuration;
+    public int taskBarExitAnimDuration;
     public int taskStackScrollDismissInfoPaneDistance;
     public int taskStackMaxDim;
     public int taskViewInfoPaneAnimDuration;
     public int taskViewRoundedCornerRadiusPx;
     public int searchBarSpaceHeightPx;
-    public int searchBarSpaceEdgeMarginsPx;
+
+    public int taskBarViewDefaultBackgroundColor;
+    public int taskBarViewDefaultTextColor;
+    public int taskBarViewLightTextColor;
+    public int taskBarViewDarkTextColor;
 
     public boolean launchedWithThumbnailAnimation;
 
@@ -72,7 +81,7 @@
         DisplayMetrics dm = res.getDisplayMetrics();
         mDisplayMetrics = dm;
 
-        boolean isLandscape = res.getConfiguration().orientation ==
+        isLandscape = res.getConfiguration().orientation ==
                 Configuration.ORIENTATION_LANDSCAPE;
         Console.log(Constants.DebugFlags.UI.MeasureAndLayout,
                 "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
@@ -87,6 +96,8 @@
                 res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
         taskBarEnterAnimDuration =
                 res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
+        taskBarExitAnimDuration =
+                res.getInteger(R.integer.recents_animate_task_bar_exit_duration);
         taskStackScrollDismissInfoPaneDistance = res.getDimensionPixelSize(
                 R.dimen.recents_task_stack_scroll_dismiss_info_pane_distance);
         taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
@@ -95,8 +106,20 @@
         taskViewRoundedCornerRadiusPx =
                 res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
         searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
-        searchBarSpaceEdgeMarginsPx =
-                res.getDimensionPixelSize(R.dimen.recents_search_bar_space_edge_margins);
+
+
+        taskBarViewDefaultBackgroundColor =
+                res.getColor(R.color.recents_task_bar_default_background_color);
+        taskBarViewDefaultTextColor =
+                res.getColor(R.color.recents_task_bar_default_text_color);
+        taskBarViewLightTextColor =
+                res.getColor(R.color.recents_task_bar_light_text_color);
+        taskBarViewDarkTextColor =
+                res.getColor(R.color.recents_task_bar_dark_text_color);
+
+        // Update the search widget id
+        SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
+        searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
     }
 
     /** Updates the system insets */
@@ -104,24 +127,57 @@
         systemInsets.set(insets);
     }
 
-    /** Returns the search bar bounds in the specified orientation */
-    public void getSearchBarBounds(int width, int height,
-                                   Rect searchBarSpaceBounds, Rect searchBarBounds) {
+    /** Updates the search bar app widget */
+    public void updateSearchBarAppWidgetId(Context context, int appWidgetId) {
+        searchBarAppWidgetId = appWidgetId;
+        SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
+        settings.edit().putInt(Constants.Values.App.Key_SearchAppWidgetId,
+                appWidgetId).apply();
+    }
+
+    /** Returns whether the search bar app widget exists */
+    public boolean hasSearchBarAppWidget() {
+        return searchBarAppWidgetId >= 0;
+    }
+
+    /**
+     * Returns the task stack bounds in the current orientation. These bounds do not account for
+     * the system insets.
+     */
+    public void getTaskStackBounds(int width, int height, Rect taskStackBounds) {
+        if (hasSearchBarAppWidget()) {
+            Rect searchBarBounds = new Rect();
+            getSearchBarBounds(width, height, searchBarBounds);
+            if (isLandscape) {
+                // In landscape, the search bar appears on the left, so shift the task rect right
+                taskStackBounds.set(searchBarBounds.width(), 0, width, height);
+            } else {
+                // In portrait, the search bar appears on the top, so shift the task rect below
+                taskStackBounds.set(0, searchBarBounds.height(), width, height);
+            }
+        } else {
+            taskStackBounds.set(0, 0, width, height);
+        }
+    }
+
+    /**
+     * Returns the search bar bounds in the current orientation.  These bounds do not account for
+     * the system insets.
+     */
+    public void getSearchBarBounds(int width, int height, Rect searchBarSpaceBounds) {
         // Return empty rects if search is not enabled
         if (!Constants.DebugFlags.App.EnableSearchButton) {
             searchBarSpaceBounds.set(0, 0, 0, 0);
-            searchBarBounds.set(0, 0, 0, 0);
             return;
         }
 
-        // Calculate the search bar bounds, and account for the system insets
-        int edgeMarginPx = searchBarSpaceEdgeMarginsPx;
-        int availableWidth = width - systemInsets.left - systemInsets.right;
-        searchBarSpaceBounds.set(0, 0, availableWidth, 2 * edgeMarginPx + searchBarSpaceHeightPx);
-
-        // Inset from the search bar space to get the search bar bounds
-        searchBarBounds.set(searchBarSpaceBounds);
-        searchBarBounds.inset(edgeMarginPx, edgeMarginPx);
+        if (isLandscape) {
+            // In landscape, the search bar appears on the left
+            searchBarSpaceBounds.set(0, 0, searchBarSpaceHeightPx, height);
+        } else {
+            // In portrait, the search bar appears on the top
+            searchBarSpaceBounds.set(0, 0, width, searchBarSpaceHeightPx);
+        }
     }
 
     /** Converts from DPs to PXs */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 36b761e..0c6ed84 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -60,39 +60,41 @@
                 Rect windowRect = data.getParcelable(AlternateRecentsComponent.KEY_WINDOW_RECT);
                 Rect systemInsets = data.getParcelable(AlternateRecentsComponent.KEY_SYSTEM_INSETS);
 
+                // NOTE: None of the rects computed below need to be offset for the status bar,
+                // since that is done when we compute the animation itself in the Recents component
+
                 // Create a dummy task stack & compute the rect for the thumbnail to animate to
                 TaskStack stack = new TaskStack(context);
                 TaskStackView tsv = new TaskStackView(context, stack);
                 Bundle replyData = new Bundle();
                 TaskViewTransform transform;
 
-                // Get the search bar bounds so that we can account for its height in the children
-                Rect searchBarSpaceBounds = new Rect();
-                Rect searchBarBounds = new Rect();
+                // Get the task stack and search bar bounds
+                Rect taskStackBounds = new Rect();
                 RecentsConfiguration config = RecentsConfiguration.getInstance();
-                config.getSearchBarBounds(windowRect.width(), windowRect.height(),
-                        searchBarSpaceBounds, searchBarBounds);
+                config.getTaskStackBounds(windowRect.width(), windowRect.height(), taskStackBounds);
 
-                // Calculate the target task rect for when there is one task
+                // Calculate the target task rect for when there is one task.
+
                 // NOTE: Since the nav bar height is already accounted for in the windowRect, don't
-                // pass in a bottom inset
+                // pass in a left or bottom inset
                 stack.addTask(new Task());
-                tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
-                        systemInsets.bottom - searchBarSpaceBounds.height(), 0);
+                tsv.computeRects(taskStackBounds.width(), taskStackBounds.height() -
+                        systemInsets.top - systemInsets.bottom, 0, 0);
                 tsv.boundScroll();
                 transform = tsv.getStackTransform(0, tsv.getStackScroll());
-                transform.rect.offset(0, searchBarSpaceBounds.height());
+                transform.rect.offset(taskStackBounds.left, taskStackBounds.top);
                 replyData.putParcelable(AlternateRecentsComponent.KEY_SINGLE_TASK_STACK_RECT,
                         new Rect(transform.rect));
 
-                // Also calculate the target task rect when there are multiple tasks
+                // Also calculate the target task rect when there are multiple tasks.
                 stack.addTask(new Task());
-                tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
-                        systemInsets.bottom - searchBarSpaceBounds.height(), 0);
+                tsv.computeRects(taskStackBounds.width(), taskStackBounds.height() -
+                        systemInsets.top - systemInsets.bottom, 0, 0);
                 tsv.setStackScrollRaw(Integer.MAX_VALUE);
                 tsv.boundScroll();
                 transform = tsv.getStackTransform(1, tsv.getStackScroll());
-                transform.rect.offset(0, searchBarSpaceBounds.height());
+                transform.rect.offset(taskStackBounds.left, taskStackBounds.top);
                 replyData.putParcelable(AlternateRecentsComponent.KEY_MULTIPLE_TASK_STACK_RECT,
                         new Rect(transform.rect));
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 52bba4a..4a19027 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -415,17 +415,23 @@
             ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
             if (info == null) continue;
 
-            String activityLabel = (t.activityLabel == null ? ssp.getActivityLabel(info) :
-                    t.activityLabel.toString());
+            ActivityManager.RecentsActivityValues av = t.activityValues;
+            String activityLabel = null;
             BitmapDrawable activityIcon = null;
-            if (t.activityIcon != null) {
-                activityIcon = new BitmapDrawable(res, t.activityIcon);
+            int activityColor = 0;
+            if (av != null) {
+                activityLabel = (av.label != null ? av.label.toString() :
+                        ssp.getActivityLabel(info));
+                activityIcon = (av.icon != null) ? new BitmapDrawable(res, av.icon) : null;
+                activityColor = av.colorPrimary;
+            } else {
+                activityLabel = ssp.getActivityLabel(info);
             }
             boolean isForemostTask = (i == (taskCount - 1));
 
             // Create a new task
             Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, activityLabel,
-                    activityIcon, t.userId);
+                    activityIcon, activityColor, t.userId);
 
             // Preload the specified number of apps
             if (i >= (taskCount - preloadCount)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index 33ac0a8..68af663 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -20,7 +20,9 @@
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
 import android.app.SearchManager;
-import android.content.ActivityNotFoundException;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -35,8 +37,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.text.TextUtils;
-import android.util.Log;
+import android.util.Pair;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -48,6 +49,7 @@
  */
 public class SystemServicesProxy {
     ActivityManager mAm;
+    AppWidgetManager mAwm;
     PackageManager mPm;
     IPackageManager mIpm;
     UserManager mUm;
@@ -59,6 +61,7 @@
     /** Private constructor */
     public SystemServicesProxy(Context context) {
         mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        mAwm = AppWidgetManager.getInstance(context);
         mPm = context.getPackageManager();
         mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mIpm = AppGlobals.getPackageManager();
@@ -91,10 +94,13 @@
                 rti.id = rti.persistentId = i;
                 rti.baseIntent = new Intent();
                 rti.baseIntent.setComponent(cn);
-                rti.description = rti.activityLabel = "" + i + " - " +
+                rti.activityValues = new ActivityManager.RecentsActivityValues();
+                rti.description = "" + i + " - " +
                         Long.toString(Math.abs(new Random().nextLong()), 36);
                 if (i % 2 == 0) {
-                    rti.activityIcon = Bitmap.createBitmap(mDummyIcon);
+                    rti.activityValues.label = rti.description;
+                    rti.activityValues.icon = Bitmap.createBitmap(mDummyIcon);
+                    rti.activityValues.colorPrimary = new Random().nextInt();
                 }
                 tasks.add(rti);
             }
@@ -103,7 +109,7 @@
 
         return mAm.getRecentTasksForUser(numTasks,
                 ActivityManager.RECENT_IGNORE_UNAVAILABLE |
-                ActivityManager.RECENT_INCLUDE_PROFILES, userId);
+                        ActivityManager.RECENT_INCLUDE_PROFILES, userId);
     }
 
     /** Returns a list of the running tasks */
@@ -162,7 +168,7 @@
     /**
      * Returns the activity info for a given component name.
      * 
-     * @param ComponentName The component name of the activity.
+     * @param cn The component name of the activity.
      * @param userId The userId of the user that this is for.
      */
     public ActivityInfo getActivityInfo(ComponentName cn, int userId) {
@@ -177,6 +183,23 @@
         }
     }
 
+    /**
+     * Returns the activity info for a given component name.
+     *
+     * @param cn The component name of the activity.
+     */
+    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;
@@ -208,27 +231,70 @@
         return icon;
     }
 
-
     /**
-     * Composes an intent to launch the global search activity.
+     * Resolves and binds the search app widget that is to appear in the recents.
      */
-    public Intent getGlobalSearchIntent(Rect sourceBounds) {
-        if (mSm == null) return null;
+    public Pair<Integer, AppWidgetProviderInfo> bindSearchAppWidget(AppWidgetHost host) {
+        if (mAwm == null) return null;
 
-        // Try and get the global search activity
+        // Ensure we have a global search activity
         ComponentName globalSearchActivity = mSm.getGlobalSearchActivity();
         if (globalSearchActivity == null) return null;
 
-        // Bundle the source of the search
-        Bundle appSearchData = new Bundle();
-        appSearchData.putString("source", mPackage);
+        // Resolve the search widget provider from the search activity
+        ActivityInfo searchActivityInfo = getActivityInfo(globalSearchActivity);
+        if (searchActivityInfo == null) return null;
 
-        // Compose the intent and Start the search activity
-        Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.setComponent(globalSearchActivity);
-        intent.putExtra(SearchManager.APP_DATA, appSearchData);
-        intent.setSourceBounds(sourceBounds);
-        return intent;
+        String key = "com.android.recents.search_widget_provider";
+        ComponentName searchWidgetCn = null;
+        Bundle searchMetaData = searchActivityInfo.metaData;
+        String searchWidgetProvider = searchMetaData.getString(key, "");
+        if (searchWidgetProvider.length() != 0) {
+            searchWidgetCn = ComponentName.unflattenFromString(searchWidgetProvider);
+        } else {
+            return null;
+        }
+
+        // Find the first Recents widget from the same package as the global search activity
+        List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders();
+        AppWidgetProviderInfo searchWidgetInfo = null;
+        for (AppWidgetProviderInfo info : widgets) {
+            if (info.provider.equals(searchWidgetCn)) {
+                searchWidgetInfo = info;
+                break;
+            }
+        }
+
+        // Return early if there is no search widget
+        if (searchWidgetInfo == null) return null;
+
+        // Allocate a new widget id and try and bind the app widget (if that fails, then just skip)
+        int searchWidgetId = host.allocateAppWidgetId();
+        Bundle opts = new Bundle();
+        opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+                AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+        if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) {
+            return null;
+        }
+        return new Pair<Integer, AppWidgetProviderInfo>(searchWidgetId, searchWidgetInfo);
+    }
+
+    /**
+     * Returns the app widget info for the specified app widget id.
+     */
+    public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
+        if (mAwm == null) return null;
+
+        return mAwm.getAppWidgetInfo(appWidgetId);
+    }
+
+    /**
+     * Destroys the specified app widget.
+     */
+    public void unbindSearchAppWidget(AppWidgetHost host, int appWidgetId) {
+        if (mAwm == null) return;
+
+        // Delete the app widget
+        host.deleteAppWidgetId(appWidgetId);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 4a1b3b2..b602f84 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents;
 
+import android.graphics.Color;
 import android.graphics.Rect;
 
 /* Common code */
@@ -46,4 +47,19 @@
             r.offset(cx, cy);
         }
     }
+
+    /** Calculates the luminance-preserved greyscale of a given color. */
+    private static int colorToGreyscale(int color) {
+        return Math.round(0.2126f * Color.red(color) + 0.7152f * Color.green(color) +
+                0.0722f * Color.blue(color));
+    }
+
+    /** Returns the ideal text color to draw on top of a specified background color. */
+    public static int getIdealTextColorForBackgroundColor(int color) {
+        RecentsConfiguration configuration = RecentsConfiguration.getInstance();
+        int greyscale = colorToGreyscale(color);
+        return (greyscale < 128) ? configuration.taskBarViewLightTextColor :
+                configuration.taskBarViewDarkTextColor;
+
+    }
 }
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 1566a49..47a506c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -72,6 +72,7 @@
     public Drawable applicationIcon;
     public Drawable activityIcon;
     public String activityLabel;
+    public int colorPrimary;
     public Bitmap thumbnail;
     public boolean isActive;
     public int userId;
@@ -83,10 +84,11 @@
     }
 
     public Task(int id, boolean isActive, Intent intent, String activityTitle,
-                BitmapDrawable activityIcon, int userId) {
+                BitmapDrawable activityIcon, int colorPrimary, int userId) {
         this.key = new TaskKey(id, intent, userId);
         this.activityLabel = activityTitle;
         this.activityIcon = activityIcon;
+        this.colorPrimary = colorPrimary;
         this.isActive = isActive;
         this.userId = userId;
     }
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 a04cd3e..c2e8275 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -27,11 +27,9 @@
 import android.net.Uri;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
-import android.widget.TextView;
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -39,7 +37,6 @@
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.R;
 
 import java.util.ArrayList;
 
@@ -57,6 +54,8 @@
 
     // The space partitioning root of this container
     SpaceNode mBSP;
+    // Whether there are any tasks
+    boolean mHasTasks;
     // Search bar view
     View mSearchBar;
     // Recents view callbacks
@@ -80,22 +79,14 @@
         mBSP = n;
 
         // Create and add all the stacks for this partition of space.
-        boolean hasTasks = false;
+        mHasTasks = false;
         removeAllViews();
         ArrayList<TaskStack> stacks = mBSP.getStacks();
         for (TaskStack stack : stacks) {
             TaskStackView stackView = new TaskStackView(getContext(), stack);
             stackView.setCallbacks(this);
             addView(stackView);
-            hasTasks |= (stack.getTaskCount() > 0);
-        }
-
-        // Create the search bar (and hide it if we have no recent tasks)
-        if (Constants.DebugFlags.App.EnableSearchButton) {
-            createSearchBar();
-            if (!hasTasks) {
-                mSearchBar.setVisibility(View.GONE);
-            }
+            mHasTasks |= (stack.getTaskCount() > 0);
         }
     }
 
@@ -130,19 +121,30 @@
         return false;
     }
 
-    /** Creates and adds the search bar */
-    void createSearchBar() {
-        // Create a temporary search bar
-        mSearchBar = mInflater.inflate(R.layout.recents_search_bar, this, false);
-        mSearchBar.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                onSearchTriggered();
+    /** Adds the search bar */
+    public void setSearchBar(View searchBar) {
+        // Create the search bar (and hide it if we have no recent tasks)
+        if (Constants.DebugFlags.App.EnableSearchButton) {
+            // Remove the previous search bar if one exists
+            if (mSearchBar != null && indexOfChild(mSearchBar) > -1) {
+                removeView(mSearchBar);
             }
-        });
-        addView(mSearchBar);
+            // Add the new search bar
+            if (searchBar != null) {
+                mSearchBar = searchBar;
+                mSearchBar.setVisibility(mHasTasks ? View.VISIBLE : View.GONE);
+                addView(mSearchBar);
+
+                Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsView|setSearchBar]",
+                        "" + (mSearchBar.getVisibility() == View.VISIBLE),
+                        Console.AnsiBlue);
+            }
+        }
     }
 
+    /**
+     * This is called with the full size of the window since we are handling our own insets.
+     */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -155,22 +157,26 @@
         Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
                 Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
 
-        // Get the search bar bounds so that we can account for its height in the children
-        Rect searchBarSpaceBounds = new Rect();
-        Rect searchBarBounds = new Rect();
+        // Get the search bar bounds and measure the search bar layout
         RecentsConfiguration config = RecentsConfiguration.getInstance();
-        config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
-                searchBarSpaceBounds, searchBarBounds);
         if (mSearchBar != null) {
-            mSearchBar.measure(MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), widthMode),
-                    MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), heightMode));
+            Rect searchBarSpaceBounds = new Rect();
+            config.getSearchBarBounds(width, height - config.systemInsets.top, searchBarSpaceBounds);
+            mSearchBar.measure(
+                    MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), MeasureSpec.EXACTLY));
         }
 
-        // We measure our stack views sans the status bar.  It will handle the nav bar itself.
+        // We give the full width of the space, not including the right nav bar insets in landscape,
+        // to the stack view, since we want the tasks to render under the search bar in landscape.
+        // In addition, we give it the full height, not including the top inset or search bar space,
+        // since we want the tasks to render under the navigation buttons in portrait.
+        Rect taskStackBounds = new Rect();
+        config.getTaskStackBounds(width, height, taskStackBounds);
         int childWidth = width - config.systemInsets.right;
-        int childHeight = height - config.systemInsets.top - searchBarSpaceBounds.height();
+        int childHeight = taskStackBounds.height() - config.systemInsets.top;
 
-        // Measure each child
+        // Measure each TaskStackView
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
@@ -183,6 +189,9 @@
         setMeasuredDimension(width, height);
     }
 
+    /**
+     * This is called with the full size of the window since we are handling our own insets.
+     */
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[RecentsView|layout]",
@@ -190,21 +199,24 @@
         Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
                 Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onLayout");
 
-        // Get the search bar bounds so that we can account for its height in the children
-        Rect searchBarSpaceBounds = new Rect();
-        Rect searchBarBounds = new Rect();
+        // Get the search bar bounds so that we lay it out
         RecentsConfiguration config = RecentsConfiguration.getInstance();
-        config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
-                searchBarSpaceBounds, searchBarBounds);
         if (mSearchBar != null) {
+            Rect searchBarSpaceBounds = new Rect();
+            config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(), searchBarSpaceBounds);
             mSearchBar.layout(config.systemInsets.left + searchBarSpaceBounds.left,
                     config.systemInsets.top + searchBarSpaceBounds.top,
                     config.systemInsets.left + mSearchBar.getMeasuredWidth(),
                     config.systemInsets.top + mSearchBar.getMeasuredHeight());
         }
 
-        // We offset our stack views by the status bar height.  It will handle the nav bar itself.
-        top += config.systemInsets.top + searchBarSpaceBounds.height();
+        // We offset the stack view by the left inset (if any), but lay it out under the search bar.
+        // In addition, we offset our stack views by the top inset and search bar height, but not
+        // the bottom insets because we want it to render under the navigation buttons.
+        Rect taskStackBounds = new Rect();
+        config.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
+        left += config.systemInsets.left;
+        top += config.systemInsets.top + taskStackBounds.top;
 
         // Layout each child
         // XXX: Based on the space node for that task view
@@ -212,9 +224,8 @@
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
             if (child instanceof TaskStackView && child.getVisibility() != GONE) {
-                int width = child.getMeasuredWidth();
-                int height = child.getMeasuredHeight();
-                child.layout(left, top, left + width, top + height);
+                TaskStackView tsv = (TaskStackView) child;
+                child.layout(left, top, left + tsv.getMeasuredWidth(), top + tsv.getMeasuredHeight());
             }
         }
     }
@@ -374,24 +385,4 @@
         TaskStackBuilder.create(getContext())
                 .addNextIntentWithParentStack(intent).startActivities();
     }
-
-    public void onSearchTriggered() {
-        // Get the search bar source bounds
-        Rect searchBarSpaceBounds = new Rect();
-        Rect searchBarBounds = new Rect();
-        RecentsConfiguration config = RecentsConfiguration.getInstance();
-        config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
-                searchBarSpaceBounds, searchBarBounds);
-
-        // Get the search intent and start it
-        Intent searchIntent = RecentsTaskLoader.getInstance().getSystemServicesProxy()
-                .getGlobalSearchIntent(searchBarBounds);
-        if (searchIntent != null) {
-            try {
-                getContext().startActivity(searchIntent);
-            } catch (ActivityNotFoundException anfe) {
-                Console.logError(getContext(), "Could not start Search activity");
-            }
-        }
-    }
 }
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 124f11e..c6cb812 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -18,11 +18,13 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.view.View;
 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.Utilities;
 import com.android.systemui.recents.model.Task;
 
 
@@ -58,6 +60,7 @@
 
     /** Binds the bar view to the task */
     void rebindToTask(Task t, boolean animate) {
+        RecentsConfiguration configuration = RecentsConfiguration.getInstance();
         mTask = t;
         // If an activity icon is defined, then we use that as the primary icon to show in the bar,
         // otherwise, we fall back to the application icon
@@ -67,6 +70,15 @@
             mApplicationIcon.setImageDrawable(t.applicationIcon);
         }
         mActivityDescription.setText(t.activityLabel);
+        // Try and apply the system ui tint
+        int tint = t.colorPrimary;
+        if (Constants.DebugFlags.App.EnableTaskBarThemeColors && tint != 0) {
+            setBackgroundColor(tint);
+            mActivityDescription.setTextColor(Utilities.getIdealTextColorForBackgroundColor(tint));
+        } else {
+            setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor);
+            mActivityDescription.setTextColor(configuration.taskBarViewDefaultTextColor);
+        }
         if (animate) {
             // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
index a81d01c..983ad49 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
@@ -29,7 +29,10 @@
 import android.widget.FrameLayout;
 import com.android.systemui.R;
 import com.android.systemui.recents.BakedBezierInterpolator;
+import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.Utilities;
+import com.android.systemui.recents.model.Task;
 
 
 /* The task info view */
@@ -143,6 +146,16 @@
                 .start();
     }
 
+    /** Binds the info view to the task */
+    void rebindToTask(Task t, boolean animate) {
+        RecentsConfiguration configuration = RecentsConfiguration.getInstance();
+        if (Constants.DebugFlags.App.EnableTaskBarThemeColors && t.colorPrimary != 0) {
+            setBackgroundColor(t.colorPrimary);
+        } else {
+            setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor);
+        }
+    }
+
     @Override
     public void draw(Canvas canvas) {
         int saveCount = 0;
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 a77e61d..e273ecf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -547,7 +547,7 @@
     }
 
     /** Computes the stack and task rects */
-    public void computeRects(int width, int height, int insetBottom) {
+    public void computeRects(int width, int height, int insetLeft, int insetBottom) {
         // Note: We let the stack view be the full height because we want the cards to go under the
         //       navigation bar if possible.  However, the stack rects which we use to calculate
         //       max scroll, etc. need to take the nav bar into account
@@ -555,6 +555,7 @@
         // Compute the stack rects
         mRect.set(0, 0, width, height);
         mStackRect.set(mRect);
+        mStackRect.left += insetLeft;
         mStackRect.bottom -= insetBottom;
 
         int smallestDimension = Math.min(width, height);
@@ -582,6 +583,11 @@
         updateMinMaxScroll(false);
     }
 
+    /**
+     * This is called with the size of the space not including the top or right insets, or the
+     * search bar height in portrait (but including the search bar width in landscape, since we want
+     * to draw under it.
+     */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -592,7 +598,9 @@
 
         // Compute our stack/task rects
         RecentsConfiguration config = RecentsConfiguration.getInstance();
-        computeRects(width, height, config.systemInsets.bottom);
+        Rect taskStackBounds = new Rect();
+        config.getTaskStackBounds(width, height, taskStackBounds);
+        computeRects(width, height, taskStackBounds.left, config.systemInsets.bottom);
 
         // Debug logging
         if (Constants.DebugFlags.UI.MeasureAndLayout) {
@@ -630,6 +638,11 @@
         setMeasuredDimension(width, height);
     }
 
+    /**
+     * This is called with the size of the space not including the top or right insets, or the
+     * search bar height in portrait (but including the search bar width in landscape, since we want
+     * to draw under it.
+     */
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[TaskStackView|layout]",
@@ -976,8 +989,6 @@
             } else {
                 mStack.filterTasks(tv.getTask());
             }
-        } else {
-            Console.logError(getContext(), "Task Filtering TBD");
         }
     }
 
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 d3b79d6..ecd0c45 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -197,18 +197,9 @@
     /** Animates this task view as it enters recents */
     public void animateOnEnterRecents() {
         RecentsConfiguration config = RecentsConfiguration.getInstance();
-        int translate = config.pxFromDp(10);
-        mBarView.setScaleX(1.25f);
-        mBarView.setScaleY(1.25f);
         mBarView.setAlpha(0f);
-        mBarView.setTranslationX(translate / 2);
-        mBarView.setTranslationY(-translate);
         mBarView.animate()
                 .alpha(1f)
-                .scaleX(1f)
-                .scaleY(1f)
-                .translationX(0)
-                .translationY(0)
                 .setStartDelay(235)
                 .setInterpolator(BakedBezierInterpolator.INSTANCE)
                 .setDuration(config.taskBarEnterAnimDuration)
@@ -219,16 +210,11 @@
     /** Animates this task view as it exits recents */
     public void animateOnLeavingRecents(final Runnable r) {
         RecentsConfiguration config = RecentsConfiguration.getInstance();
-        int translate = config.pxFromDp(10);
         mBarView.animate()
             .alpha(0f)
-            .scaleX(1.1f)
-            .scaleY(1.1f)
-            .translationX(translate / 2)
-            .translationY(-translate)
             .setStartDelay(0)
             .setInterpolator(BakedBezierInterpolator.INSTANCE)
-            .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
+            .setDuration(config.taskBarExitAnimDuration)
             .withLayer()
             .withEndAction(new Runnable() {
                 @Override
@@ -352,6 +338,7 @@
             // Bind each of the views to the new task data
             mThumbnailView.rebindToTask(mTask, reloadingTaskData);
             mBarView.rebindToTask(mTask, reloadingTaskData);
+            mInfoView.rebindToTask(mTask, reloadingTaskData);
             // Rebind any listeners
             mBarView.mApplicationIcon.setOnClickListener(this);
             mInfoView.mAppInfoButton.setOnClickListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 0f32dc0..1c88ea7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -16,12 +16,18 @@
 
 package com.android.systemui.statusbar;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
-import android.widget.FrameLayout;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
 
 import com.android.internal.R;
 
@@ -34,7 +40,6 @@
     private static final long DOUBLETAP_TIMEOUT_MS = 1000;
 
     private boolean mDimmed;
-    private boolean mLocked;
 
     private int mBgResId = R.drawable.notification_quantum_bg;
     private int mDimmedBgResId = R.drawable.notification_quantum_bg_dim;
@@ -51,13 +56,20 @@
 
     private OnActivatedListener mOnActivatedListener;
 
+    protected Drawable mBackgroundNormal;
+    protected Drawable mBackgroundDimmed;
+    private ObjectAnimator mBackgroundAnimator;
+    private Interpolator mFastOutSlowInInterpolator;
+
     public ActivatableNotificationView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         updateBackgroundResource();
+        setWillNotDraw(false);
+        mFastOutSlowInInterpolator =
+                AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
     }
 
-
     private final Runnable mTapTimeoutRunnable = new Runnable() {
         @Override
         public void run() {
@@ -66,20 +78,51 @@
     };
 
     @Override
+    protected void onDraw(Canvas canvas) {
+        draw(canvas, mBackgroundNormal);
+        draw(canvas, mBackgroundDimmed);
+    }
+
+    private void draw(Canvas canvas, Drawable drawable) {
+        if (drawable != null) {
+            drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight);
+            drawable.draw(canvas);
+        }
+    }
+
+    @Override
+    protected boolean verifyDrawable(Drawable who) {
+        return super.verifyDrawable(who) || who == mBackgroundNormal
+                || who == mBackgroundDimmed;
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        drawableStateChanged(mBackgroundNormal);
+        drawableStateChanged(mBackgroundDimmed);
+    }
+
+    private void drawableStateChanged(Drawable d) {
+        if (d != null && d.isStateful()) {
+            d.setState(getDrawableState());
+        }
+    }
+
+    @Override
     public void setOnClickListener(OnClickListener l) {
         super.setOnClickListener(l);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        if (mLocked) {
-            return handleTouchEventLocked(event);
+        if (mDimmed) {
+            return handleTouchEventDimmed(event);
         } else {
             return super.onTouchEvent(event);
         }
     }
 
-    private boolean handleTouchEventLocked(MotionEvent event) {
+    private boolean handleTouchEventDimmed(MotionEvent event) {
         int action = event.getActionMasked();
         switch (action) {
             case MotionEvent.ACTION_DOWN:
@@ -88,14 +131,6 @@
                 if (mDownY > getActualHeight()) {
                     return false;
                 }
-
-                // Call the listener tentatively directly, even if we don't know whether the user
-                // will stay within the touch slop, as the listener is implemented as a scale
-                // animation, which is cancellable without jarring effects when swiping away
-                // notifications.
-                if (mOnActivatedListener != null) {
-                    mOnActivatedListener.onActivated(this);
-                }
                 break;
             case MotionEvent.ACTION_MOVE:
                 if (!isWithinTouchSlop(event)) {
@@ -109,8 +144,8 @@
                         makeActive(event.getX(), event.getY());
                         postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
                     } else {
-                        performClick();
                         makeInactive();
+                        performClick();
                     }
                 } else {
                     makeInactive();
@@ -126,8 +161,11 @@
     }
 
     private void makeActive(float x, float y) {
-        mCustomBackground.setHotspot(0, x, y);
+        mBackgroundDimmed.setHotspot(0, x, y);
         mActivated = true;
+        if (mOnActivatedListener != null) {
+            mOnActivatedListener.onActivated(this);
+        }
     }
 
     /**
@@ -136,8 +174,8 @@
     private void makeInactive() {
         if (mActivated) {
             // Make sure that we clear the hotspot from the center.
-            mCustomBackground.setHotspot(0, getWidth() / 2, getActualHeight() / 2);
-            mCustomBackground.removeHotspot(0);
+            mBackgroundDimmed.setHotspot(0, getWidth() / 2, getActualHeight() / 2);
+            mBackgroundDimmed.removeHotspot(0);
             mActivated = false;
         }
         if (mOnActivatedListener != null) {
@@ -153,23 +191,22 @@
 
     /**
      * Sets the notification as dimmed, meaning that it will appear in a more gray variant.
+     *
+     * @param dimmed Whether the notification should be dimmed.
+     * @param fade Whether an animation should be played to change the state.
      */
-    public void setDimmed(boolean dimmed) {
+    public void setDimmed(boolean dimmed, boolean fade) {
         if (mDimmed != dimmed) {
             mDimmed = dimmed;
-            updateBackgroundResource();
+            if (fade) {
+                fadeBackgroundResource();
+            } else {
+                updateBackgroundResource();
+            }
         }
     }
 
     /**
-     * Sets the notification as locked. In the locked state, the first tap will produce a quantum
-     * ripple to make the notification brighter and only the second tap will cause a click.
-     */
-    public void setLocked(boolean locked) {
-        mLocked = locked;
-    }
-
-    /**
      * Sets the resource id for the background of this notification.
      *
      * @param bgResId The background resource to use in normal state.
@@ -181,20 +218,111 @@
         updateBackgroundResource();
     }
 
+    private void fadeBackgroundResource() {
+        if (mDimmed) {
+            setBackgroundDimmed(mDimmedBgResId);
+        } else {
+            setBackgroundNormal(mBgResId);
+        }
+        int startAlpha = mDimmed ? 255 : 0;
+        int endAlpha = mDimmed ? 0 : 255;
+        int duration = NotificationActivator.ANIMATION_LENGTH_MS;
+        // Check whether there is already a background animation running.
+        if (mBackgroundAnimator != null) {
+            startAlpha = (Integer) mBackgroundAnimator.getAnimatedValue();
+            duration = (int) mBackgroundAnimator.getCurrentPlayTime();
+            mBackgroundAnimator.removeAllListeners();
+            mBackgroundAnimator.cancel();
+            if (duration <= 0) {
+                updateBackgroundResource();
+                return;
+            }
+        }
+        mBackgroundNormal.setAlpha(startAlpha);
+        mBackgroundAnimator =
+                ObjectAnimator.ofInt(mBackgroundNormal, "alpha", startAlpha, endAlpha);
+        mBackgroundAnimator.setInterpolator(mFastOutSlowInInterpolator);
+        mBackgroundAnimator.setDuration(duration);
+        mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (mDimmed) {
+                    setBackgroundNormal(null);
+                } else {
+                    setBackgroundDimmed(null);
+                }
+                mBackgroundAnimator = null;
+            }
+        });
+        mBackgroundAnimator.start();
+    }
+
     private void updateBackgroundResource() {
-        setCustomBackgroundResource(mDimmed ? mDimmedBgResId : mBgResId);
+        if (mDimmed) {
+            setBackgroundDimmed(mDimmedBgResId);
+            mBackgroundDimmed.setAlpha(255);
+            setBackgroundNormal(null);
+        } else {
+            setBackgroundDimmed(null);
+            setBackgroundNormal(mBgResId);
+            mBackgroundNormal.setAlpha(255);
+        }
+    }
+
+    /**
+     * Sets a background drawable for the normal state. As we need to change our bounds
+     * independently of layout, we need the notion of a background independently of the regular View
+     * background..
+     */
+    private void setBackgroundNormal(Drawable backgroundNormal) {
+        if (mBackgroundNormal != null) {
+            mBackgroundNormal.setCallback(null);
+            unscheduleDrawable(mBackgroundNormal);
+        }
+        mBackgroundNormal = backgroundNormal;
+        if (mBackgroundNormal != null) {
+            mBackgroundNormal.setCallback(this);
+        }
+        invalidate();
+    }
+
+    private void setBackgroundDimmed(Drawable overlay) {
+        if (mBackgroundDimmed != null) {
+            mBackgroundDimmed.setCallback(null);
+            unscheduleDrawable(mBackgroundDimmed);
+        }
+        mBackgroundDimmed = overlay;
+        if (mBackgroundDimmed != null) {
+            mBackgroundDimmed.setCallback(this);
+        }
+        invalidate();
+    }
+
+    private void setBackgroundNormal(int drawableResId) {
+        setBackgroundNormal(getResources().getDrawable(drawableResId));
+    }
+
+    private void setBackgroundDimmed(int drawableResId) {
+        setBackgroundDimmed(getResources().getDrawable(drawableResId));
     }
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        setPivotX(getWidth()/2);
+        setPivotX(getWidth() / 2);
     }
 
     @Override
     public void setActualHeight(int actualHeight) {
         super.setActualHeight(actualHeight);
-        setPivotY(actualHeight/2);
+        invalidate();
+        setPivotY(actualHeight / 2);
+    }
+
+    @Override
+    public void setClipTopAmount(int clipTopAmount) {
+        super.setClipTopAmount(clipTopAmount);
+        invalidate();
     }
 
     public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 360f4bf..2c7464a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -167,7 +167,12 @@
 
     protected int mZenMode;
 
-    protected boolean mOnKeyguard;
+    /**
+     * The {@link StatusBarState} of the status bar.
+     */
+    protected int mState;
+    protected boolean mBouncerShowing;
+
     protected NotificationOverflowContainer mKeyguardIconOverflowContainer;
 
     public boolean isDeviceProvisioned() {
@@ -1050,9 +1055,10 @@
         mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
         int n = mNotificationData.size();
         int visibleNotifications = 0;
+        boolean onKeyguard = mState == StatusBarState.KEYGUARD;
         for (int i = n-1; i >= 0; i--) {
             NotificationData.Entry entry = mNotificationData.get(i);
-            if (mOnKeyguard) {
+            if (onKeyguard) {
                 entry.row.setExpansionDisabled(true);
             } else {
                 entry.row.setExpansionDisabled(false);
@@ -1061,10 +1067,9 @@
                     entry.row.setSystemExpanded(top);
                 }
             }
-            entry.row.setDimmed(mOnKeyguard);
-            entry.row.setLocked(mOnKeyguard);
+            entry.row.setDimmed(onKeyguard, false /* fade */);
             boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
-            if (mOnKeyguard && (visibleNotifications >= maxKeyguardNotifications
+            if (onKeyguard && (visibleNotifications >= maxKeyguardNotifications
                     || !showOnKeyguard)) {
                 entry.row.setVisibility(View.GONE);
                 if (showOnKeyguard) {
@@ -1080,8 +1085,9 @@
             }
         }
 
-        if (mOnKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) {
+        if (onKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) {
             mKeyguardIconOverflowContainer.setVisibility(View.VISIBLE);
+            mKeyguardIconOverflowContainer.setDimmed(true /* dimmed */, false /* fade */);
         } else {
             mKeyguardIconOverflowContainer.setVisibility(View.GONE);
         }
@@ -1276,7 +1282,7 @@
             if (userChangedExpansion) {
                 boolean userExpanded = oldEntry.row.isUserExpanded();
                 newEntry.row.setUserExpanded(userExpanded);
-                newEntry.row.applyExpansionToLayout();
+                newEntry.row.notifyHeightChanged();
             }
         }
 
@@ -1390,6 +1396,17 @@
         // hook for subclasses
     }
 
+    public void setBouncerShowing(boolean bouncerShowing) {
+        mBouncerShowing = bouncerShowing;
+    }
+
+    /**
+     * @return Whether the security bouncer from Keyguard is showing.
+     */
+    public boolean isBouncerShowing() {
+        return mBouncerShowing;
+    }
+
     public void destroy() {
         if (mSearchPanelView != null) {
             mWindowManager.removeViewImmediate(mSearchPanelView);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
new file mode 100644
index 0000000..e471754
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -0,0 +1,206 @@
+/*
+ * 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;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import com.android.systemui.ExpandHelper;
+import com.android.systemui.Gefingerpoken;
+import com.android.systemui.R;
+
+/**
+ * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
+ * the notification where the drag started.
+ */
+public class DragDownHelper implements Gefingerpoken {
+
+    private static final float RUBBERBAND_FACTOR_EXPANDABLE = 0.5f;
+    private static final float RUBBERBAND_FACTOR_STATIC = 0.15f;
+
+    private static final int SPRING_BACK_ANIMATION_LENGTH_MS = 375;
+
+    private int mMinDragDistance;
+    private ExpandHelper.Callback mCallback;
+    private float mInitialTouchX;
+    private float mInitialTouchY;
+    private boolean mDraggingDown;
+    private float mTouchSlop;
+    private OnDragDownListener mOnDragDownListener;
+    private View mHost;
+    private final int[] mTemp2 = new int[2];
+    private boolean mDraggedFarEnough;
+    private ExpandableView mStartingChild;
+    private Interpolator mInterpolator;
+
+    public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
+            OnDragDownListener onDragDownListener) {
+        mMinDragDistance = context.getResources().getDimensionPixelSize(
+                R.dimen.keyguard_drag_down_min_distance);
+        mInterpolator =
+                AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        mCallback = callback;
+        mOnDragDownListener = onDragDownListener;
+        mHost = host;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        final float x = event.getX();
+        final float y = event.getY();
+
+        switch (event.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                mDraggedFarEnough = false;
+                mDraggingDown = false;
+                mStartingChild = null;
+                mInitialTouchY = y;
+                mInitialTouchX = x;
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                final float h = y - mInitialTouchY;
+                if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) {
+                    mDraggingDown = true;
+                    captureStartingChild(mInitialTouchX, mInitialTouchY);
+                    mInitialTouchY = y;
+                    mInitialTouchX = x;
+                    return true;
+                }
+                break;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (!mDraggingDown) {
+            return false;
+        }
+        final float x = event.getX();
+        final float y = event.getY();
+
+        switch (event.getActionMasked()) {
+            case MotionEvent.ACTION_MOVE:
+                final float h = y - mInitialTouchY;
+                captureStartingChild(mInitialTouchX, mInitialTouchY);
+                if (mStartingChild != null) {
+                    handleExpansion(h, mStartingChild);
+                }
+                if (h > mMinDragDistance) {
+                    if (!mDraggedFarEnough) {
+                        mDraggedFarEnough = true;
+                        mOnDragDownListener.onThresholdReached();
+                    }
+                } else {
+                    if (mDraggedFarEnough) {
+                        mDraggedFarEnough = false;
+                        mOnDragDownListener.onReset();
+                    }
+                }
+                return true;
+            case MotionEvent.ACTION_UP:
+                if (mDraggedFarEnough) {
+                    if (mStartingChild != null) {
+                        mCallback.setUserLockedChild(mStartingChild, false);
+                    }
+                    mOnDragDownListener.onDraggedDown(mStartingChild);
+                    mDraggingDown = false;
+                } else {
+                    stopDragging();
+                    return false;
+                }
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                stopDragging();
+                return false;
+        }
+        return false;
+    }
+
+    private void captureStartingChild(float x, float y) {
+        if (mStartingChild == null) {
+            mStartingChild = findView(x, y);
+            if (mStartingChild != null) {
+                mCallback.setUserLockedChild(mStartingChild, true);
+            }
+        }
+    }
+
+    private void handleExpansion(float heightDelta, ExpandableView child) {
+        if (heightDelta < 0) {
+            heightDelta = 0;
+        }
+        boolean expandable = child.isContentExpandable();
+        float rubberbandFactor = expandable
+                ? RUBBERBAND_FACTOR_EXPANDABLE
+                : RUBBERBAND_FACTOR_STATIC;
+        float rubberband = heightDelta * rubberbandFactor;
+        if (expandable && (rubberband + child.getMinHeight()) > child.getMaxHeight()) {
+            float overshoot = (rubberband + child.getMinHeight()) - child.getMaxHeight();
+            overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
+            rubberband -= overshoot;
+        }
+        child.setActualHeight((int) (child.getMinHeight() + rubberband));
+    }
+
+    private void cancelExpansion(final ExpandableView child) {
+        if (child.getActualHeight() == child.getMinHeight()) {
+            return;
+        }
+        ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
+                child.getActualHeight(), child.getMinHeight());
+        anim.setInterpolator(mInterpolator);
+        anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mCallback.setUserLockedChild(child, false);
+            }
+        });
+        anim.start();
+    }
+
+    private void stopDragging() {
+        if (mStartingChild != null) {
+            cancelExpansion(mStartingChild);
+        }
+        mDraggingDown = false;
+        mOnDragDownListener.onReset();
+    }
+
+    private ExpandableView findView(float x, float y) {
+        mHost.getLocationOnScreen(mTemp2);
+        x += mTemp2[0];
+        y += mTemp2[1];
+        return mCallback.getChildAtRawPosition(x, y);
+    }
+
+    public interface OnDragDownListener {
+        void onDraggedDown(View startingChild);
+        void onReset();
+        void onThresholdReached();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 61aad6f..e5512a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -64,7 +64,7 @@
         mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
         mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
 
-        mActivator = new NotificationActivator(this);
+        mActivator = new NotificationActivator(this, this);
     }
 
     @Override
@@ -137,7 +137,7 @@
      */
     public void setSystemExpanded(boolean expand) {
         mIsSystemExpanded = expand;
-        applyExpansionToLayout();
+        notifyHeightChanged();
     }
 
     /**
@@ -145,7 +145,7 @@
      */
     public void setExpansionDisabled(boolean expansionDisabled) {
         mExpansionDisabled = expansionDisabled;
-        applyExpansionToLayout();
+        notifyHeightChanged();
     }
 
     /**
@@ -160,13 +160,8 @@
         }
     }
 
-    /**
-     * If {@link #isExpanded()} then this is the greatest possible height this view can
-     * get and otherwise it is {@link #mRowMinHeight}.
-     *
-     * @return the maximum allowed expansion height of this view.
-     */
-    public int getMaximumAllowedExpandHeight() {
+    @Override
+    public int getIntrinsicHeight() {
         if (isUserLocked()) {
             return getActualHeight();
         }
@@ -216,9 +211,10 @@
     /**
      * Sets the notification as dimmed, meaning that it will appear in a more gray variant.
      */
-    public void setDimmed(boolean dimmed) {
-        super.setDimmed(dimmed);
-        mActivator.setDimmed(dimmed);
+    @Override
+    public void setDimmed(boolean dimmed, boolean fade) {
+        super.setDimmed(dimmed, fade);
+        mActivator.setDimmed(dimmed, fade);
     }
 
     public int getMaxExpandHeight() {
@@ -233,7 +229,12 @@
      * @return the potential height this view could expand in addition.
      */
     public int getExpandPotential() {
-        return getMaximumAllowedExpandHeight() - getActualHeight();
+        return getIntrinsicHeight() - getActualHeight();
+    }
+
+    @Override
+    public boolean isContentExpandable() {
+        return mPrivateLayout.isContentExpandable();
     }
 
     @Override
@@ -249,6 +250,11 @@
     }
 
     @Override
+    public int getMinHeight() {
+        return mPrivateLayout.getMinHeight();
+    }
+
+    @Override
     public void setClipTopAmount(int clipTopAmount) {
         super.setClipTopAmount(clipTopAmount);
         mPrivateLayout.setClipTopAmount(clipTopAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 35913fa..33e9051 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -23,6 +23,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.InsetDrawable;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.FrameLayout;
 
@@ -34,7 +35,6 @@
     private OnHeightChangedListener mOnHeightChangedListener;
     protected int mActualHeight;
     protected int mClipTopAmount;
-    protected Drawable mCustomBackground;
     private boolean mActualHeightInitialized;
 
     public ExpandableView(Context context, AttributeSet attrs) {
@@ -42,27 +42,6 @@
     }
 
     @Override
-    protected void onDraw(Canvas canvas) {
-        if (mCustomBackground != null) {
-            mCustomBackground.setBounds(0, mClipTopAmount, getWidth(), mActualHeight);
-            mCustomBackground.draw(canvas);
-        }
-    }
-
-    @Override
-    protected boolean verifyDrawable(Drawable who) {
-        return super.verifyDrawable(who) || who == mCustomBackground;
-    }
-
-    @Override
-    protected void drawableStateChanged() {
-        final Drawable d = mCustomBackground;
-        if (d != null && d.isStateful()) {
-            d.setState(getDrawableState());
-        }
-    }
-
-    @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         if (!mActualHeightInitialized && mActualHeight == 0) {
@@ -71,22 +50,32 @@
         mActualHeightInitialized = true;
     }
 
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (filterMotionEvent(ev)) {
+            return super.dispatchTouchEvent(ev);
+        }
+        return false;
+    }
+
+    private boolean filterMotionEvent(MotionEvent event) {
+        return event.getActionMasked() != MotionEvent.ACTION_DOWN
+                || event.getY() > mClipTopAmount && event.getY() < mActualHeight;
+    }
+
     /**
      * Sets the actual height of this notification. This is different than the laid out
      * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
      */
     public void setActualHeight(int actualHeight) {
         mActualHeight = actualHeight;
-        invalidate();
-        if (mOnHeightChangedListener != null) {
-            mOnHeightChangedListener.onHeightChanged(this);
-        }
+        notifyHeightChanged();
     }
 
     /**
      * See {@link #setActualHeight}.
      *
-     * @return The actual height of this notification.
+     * @return The current actual height of this notification.
      */
     public int getActualHeight() {
         return mActualHeight;
@@ -95,7 +84,23 @@
     /**
      * @return The maximum height of this notification.
      */
-    public abstract int getMaxHeight();
+    public int getMaxHeight() {
+        return getHeight();
+    }
+
+    /**
+     * @return The minimum height of this notification.
+     */
+    public int getMinHeight() {
+        return getHeight();
+    }
+
+    /**
+     * @return The desired notification height.
+     */
+    public int getIntrinsicHeight() {
+        return mActualHeight;
+    }
 
     /**
      * Sets the amount this view should be clipped from the top. This is used when an expanded
@@ -105,7 +110,6 @@
      */
     public void setClipTopAmount(int clipTopAmount) {
         mClipTopAmount = clipTopAmount;
-        invalidate();
     }
 
     public void setOnHeightChangedListener(OnHeightChangedListener listener) {
@@ -113,22 +117,16 @@
     }
 
     /**
-     * Sets a custom background drawable. As we need to change our bounds independently of layout,
-     * we need the notition of a custom background.
+     * @return Whether we can expand this views content.
      */
-    public void setCustomBackground(Drawable customBackground) {
-        if (mCustomBackground != null) {
-            mCustomBackground.setCallback(null);
-            unscheduleDrawable(mCustomBackground);
-        }
-        mCustomBackground = customBackground;
-        mCustomBackground.setCallback(this);
-        setWillNotDraw(customBackground == null);
-        invalidate();
+    public boolean isContentExpandable() {
+        return false;
     }
 
-    public void setCustomBackgroundResource(int drawableResId) {
-        setCustomBackground(getResources().getDrawable(drawableResId));
+    public void notifyHeightChanged() {
+        if (mOnHeightChangedListener != null) {
+            mOnHeightChangedListener.onHeightChanged(this);
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java
index 620e457..a03aeec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java
@@ -30,18 +30,44 @@
  */
 public class NotificationActivator {
 
-    private static final int ANIMATION_LENGTH_MS = 220;
+    public static final int ANIMATION_LENGTH_MS = 220;
     private static final float INVERSE_ALPHA = 0.9f;
     private static final float DIMMED_SCALE = 0.95f;
 
-    private final View mTargetView;
+    /**
+     * Normal state. Notification is fully interactable.
+     */
+    private static final int STATE_NORMAL = 0;
 
+    /**
+     * Dimmed state. Neutral state when on the lockscreen, with slight transparency and scaled down
+     * a bit.
+     */
+    private static final int STATE_DIMMED = 1;
+
+    /**
+     * Activated state. Used after tapping a notification on the lockscreen. Normal transparency and
+     * normal scale.
+     */
+    private static final int STATE_ACTIVATED = 2;
+
+    /**
+     * Inverse activated state. Used for the other notifications on the lockscreen when tapping on
+     * one.
+     */
+    private static final int STATE_ACTIVATED_INVERSE = 3;
+
+    private final View mTargetView;
+    private final View mHotspotView;
     private final Interpolator mFastOutSlowInInterpolator;
     private final Interpolator mLinearOutSlowInInterpolator;
     private final int mTranslationZ;
 
-    public NotificationActivator(View targetView) {
+    private int mState;
+
+    public NotificationActivator(View targetView, View hotspotView) {
         mTargetView = targetView;
+        mHotspotView = hotspotView;
         Context ctx = targetView.getContext();
         mFastOutSlowInInterpolator =
                 AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_slow_in);
@@ -53,18 +79,37 @@
     }
 
     public void activateInverse() {
+        if (mState == STATE_ACTIVATED_INVERSE) {
+            return;
+        }
+        mTargetView.animate().cancel();
         mTargetView.animate().withLayer().alpha(INVERSE_ALPHA);
+        mState = STATE_ACTIVATED_INVERSE;
+    }
+
+    public void addHotspot() {
+        mHotspotView.getBackground().setHotspot(
+                0, mHotspotView.getWidth()/2, mHotspotView.getHeight()/2);
     }
 
     public void activate() {
+        if (mState == STATE_ACTIVATED) {
+            return;
+        }
+        mTargetView.animate().cancel();
         mTargetView.animate()
                 .setInterpolator(mLinearOutSlowInInterpolator)
                 .scaleX(1)
                 .scaleY(1)
                 .translationZBy(mTranslationZ);
+        mState = STATE_ACTIVATED;
     }
 
     public void reset() {
+        if (mState == STATE_DIMMED) {
+            return;
+        }
+        mTargetView.animate().cancel();
         mTargetView.animate()
                 .setInterpolator(mFastOutSlowInInterpolator)
                 .scaleX(DIMMED_SCALE)
@@ -73,15 +118,35 @@
         if (mTargetView.getAlpha() != 1.0f) {
             mTargetView.animate().withLayer().alpha(1);
         }
+        mState = STATE_DIMMED;
     }
 
-    public void setDimmed(boolean dimmed) {
+    public void setDimmed(boolean dimmed, boolean fade) {
         if (dimmed) {
-            mTargetView.setScaleX(DIMMED_SCALE);
-            mTargetView.setScaleY(DIMMED_SCALE);
+            mTargetView.animate().cancel();
+            if (fade) {
+                mTargetView.animate()
+                        .setInterpolator(mFastOutSlowInInterpolator)
+                        .scaleX(DIMMED_SCALE)
+                        .scaleY(DIMMED_SCALE);
+            } else {
+                mTargetView.setScaleX(DIMMED_SCALE);
+                mTargetView.setScaleY(DIMMED_SCALE);
+            }
+            mState = STATE_DIMMED;
         } else {
-            mTargetView.setScaleX(1);
-            mTargetView.setScaleY(1);
+            mTargetView.animate().cancel();
+            if (fade) {
+                mTargetView.animate()
+                        .setInterpolator(mFastOutSlowInInterpolator)
+                        .scaleX(1)
+                        .scaleY(1);
+            } else {
+                mTargetView.animate().cancel();
+                mTargetView.setScaleX(1);
+                mTargetView.setScaleY(1);
+            }
+            mState = STATE_NORMAL;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index fd0cb08..1f15eaf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -84,6 +84,11 @@
     }
 
     @Override
+    public int getMinHeight() {
+        return mSmallHeight;
+    }
+
+    @Override
     public void setClipTopAmount(int clipTopAmount) {
         super.setClipTopAmount(clipTopAmount);
         updateClipping();
@@ -125,4 +130,9 @@
     public void notifyContentUpdated() {
         selectLayout();
     }
+
+    @Override
+    public boolean isContentExpandable() {
+        return mExpandedChild != null;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
index 8ebd50d..e6b5600 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
@@ -45,11 +45,6 @@
     }
 
     @Override
-    public int getMaxHeight() {
-        return getHeight();
-    }
-
-    @Override
     public void setClipTopAmount(int clipTopAmount) {
         // noop
     }
@@ -60,10 +55,14 @@
         mIconsView = (NotificationOverflowIconsView) findViewById(R.id.overflow_icons_view);
         mIconsView.setMoreText((TextView) findViewById(R.id.more_text));
 
-        mActivator = new NotificationActivator(this);
-        mActivator.setDimmed(true);
-        setLocked(true);
-        setDimmed(true);
+        mActivator = new NotificationActivator(this, this);
+        setDimmed(true, false);
+    }
+
+    @Override
+    public void setDimmed(boolean dimmed, boolean fade) {
+        super.setDimmed(dimmed, fade);
+        mActivator.setDimmed(dimmed, fade);
     }
 
     public NotificationOverflowIconsView getIconsView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java
new file mode 100644
index 0000000..9d75228
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.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;
+
+/**
+ * Class to encapsulate all possible status bar states regarding Keyguard.
+ */
+public class StatusBarState {
+
+    /**
+     * The status bar is in the "normal" shade mode.
+     */
+    public static final int SHADE = 0;
+
+    /**
+     * Status bar is currently the Keyguard.
+     */
+    public static final int KEYGUARD = 1;
+
+    /**
+     * Status bar is in the special mode, where it is fully interactive but still locked. So
+     * dismissing the shade will still show the bouncer.
+     */
+    public static final int SHADE_LOCKED = 2;
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 3fae3f0..089757a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -39,6 +39,7 @@
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
@@ -142,6 +143,14 @@
         }
     };
 
+    private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View view) {
+            ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
+                    .showInputMethodPicker();
+        }
+    };
+
     private class H extends Handler {
         public void handleMessage(Message m) {
             switch (m.what) {
@@ -233,6 +242,10 @@
         return mCurrentView.findViewById(R.id.home);
     }
 
+    public View getImeSwitchButton() {
+        return mCurrentView.findViewById(R.id.ime_switcher);
+    }
+
     // for when home is disabled, but search isn't
     public View getSearchLight() {
         return mCurrentView.findViewById(R.id.search_light);
@@ -283,6 +296,12 @@
 
         ((ImageView)getRecentsButton()).setImageDrawable(mVertical ? mRecentLandIcon : mRecentIcon);
 
+        final boolean showImeButton = ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
+        getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
+        // Update menu button in case the IME state has changed.
+        setMenuVisibility(mShowMenu, true);
+
+
         setDisabledFlags(mDisabledFlags, true);
     }
 
@@ -363,7 +382,10 @@
 
         mShowMenu = show;
 
-        getMenuButton().setVisibility(mShowMenu ? View.VISIBLE : View.INVISIBLE);
+        // Only show Menu if IME switcher not shown.
+        final boolean shouldShow = mShowMenu &&
+                ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
+        getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
     }
 
     @Override
@@ -379,6 +401,8 @@
 
         mCurrentView = mRotatedViews[Surface.ROTATION_0];
 
+        getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
+
         watchForAccessibilityChanges();
     }
 
@@ -424,6 +448,8 @@
         mCurrentView = mRotatedViews[rot];
         mCurrentView.setVisibility(View.VISIBLE);
 
+        getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
+
         mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
 
         // force the low profile & disabled states into compliance
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 82fbb16..627b80f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -25,6 +25,7 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.GestureRecorder;
+import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 public class NotificationPanelView extends PanelView implements
@@ -36,11 +37,9 @@
     private View mKeyguardStatusView;
 
     private NotificationStackScrollLayout mNotificationStackScroller;
-    private int[] mTempLocation = new int[2];
-    private int[] mTempChildLocation = new int[2];
-    private View mNotificationParent;
     private boolean mTrackingSettings;
-    private float mExpandedHeight = -1;
+    private int mNotificationTopPadding;
+    private boolean mAnimateNextTopPaddingChange;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -70,7 +69,25 @@
         mNotificationStackScroller = (NotificationStackScrollLayout)
                 findViewById(R.id.notification_stack_scroller);
         mNotificationStackScroller.setOnHeightChangedListener(this);
-        mNotificationParent = findViewById(R.id.notification_container_parent);
+        mNotificationTopPadding = getResources().getDimensionPixelSize(
+                R.dimen.notifications_top_padding);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        int keyguardBottomMargin =
+                ((MarginLayoutParams) mKeyguardStatusView.getLayoutParams()).bottomMargin;
+        mNotificationStackScroller.setTopPadding(mStatusBar.getBarState() == StatusBarState.KEYGUARD
+                ? mKeyguardStatusView.getBottom() + keyguardBottomMargin
+                : mHeader.getBottom() + mNotificationTopPadding,
+                mAnimateNextTopPaddingChange);
+        mAnimateNextTopPaddingChange = false;
+    }
+
+    public void animateNextTopPaddingChange() {
+        mAnimateNextTopPaddingChange = true;
+        requestLayout();
     }
 
     @Override
@@ -95,30 +112,22 @@
         return super.dispatchPopulateAccessibilityEvent(event);
     }
 
-    /**
-     * 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 onInterceptTouchEvent(MotionEvent event) {
         // intercept for quick settings
         if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            final View target = mStatusBar.isOnKeyguard() ?  mKeyguardStatusView : mHeader;
+            final View target = mStatusBar.getBarState() == StatusBarState.KEYGUARD
+                    ? mKeyguardStatusView
+                    : mHeader;
             final boolean inTarget = PhoneStatusBar.inBounds(target, event, true);
             if (inTarget && !isInSettings()) {
                 mTrackingSettings = true;
+                requestDisallowInterceptTouchEvent(true);
                 return true;
             }
             if (!inTarget && isInSettings()) {
                 mTrackingSettings = true;
+                requestDisallowInterceptTouchEvent(true);
                 return true;
             }
         }
@@ -167,42 +176,7 @@
 
     @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) {
-        if (mExpandedHeight == expandedHeight) return;
-        mExpandedHeight = expandedHeight;
-        mNotificationStackScroller.setIsExpanded(expandedHeight > 0.0f);
-        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)));
-        }
+        mNotificationStackScroller.setStackHeight(expandedHeight);
     }
 
     @Override
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 545352c..0db6914 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -18,6 +18,7 @@
 
 
 import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
 import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.windowStateToString;
@@ -95,6 +96,8 @@
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.DragDownHelper;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.InterceptedNotifications;
 import com.android.systemui.statusbar.NotificationData;
@@ -102,6 +105,7 @@
 import com.android.systemui.statusbar.NotificationOverflowContainer;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.DateView;
@@ -119,7 +123,8 @@
 import java.util.Collection;
 import java.util.Collections;
 
-public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
+public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
+        DragDownHelper.OnDragDownListener {
     static final String TAG = "PhoneStatusBar";
     public static final boolean DEBUG = BaseStatusBar.DEBUG;
     public static final boolean SPEW = false;
@@ -232,6 +237,7 @@
     View mNotificationPanelHeader;
     View mKeyguardStatusView;
     View mKeyguardBottomArea;
+    boolean mLeaveOpenOnKeyguardHide;
     KeyguardIndicationTextView mKeyguardIndicationTextView;
 
     // TODO: Fetch phrase from search/hotword provider.
@@ -379,7 +385,7 @@
     private boolean mSettingsStarted;
     private boolean mSettingsCancelled;
     private boolean mSettingsClosing;
-    private int mNotificationPadding;
+    private boolean mVisible;
 
     private final OnChildLocationsChangedListener mOnChildLocationsChangedListener =
             new OnChildLocationsChangedListener() {
@@ -469,6 +475,13 @@
         }
     };
 
+    private final View.OnClickListener mOverflowClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            goToLockedShade(null);
+        }
+    };
+
     @Override
     public void setZenMode(int mode) {
         super.setZenMode(mode);
@@ -618,6 +631,8 @@
                         R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
         mKeyguardIconOverflowContainer.setOnActivatedListener(this);
         mKeyguardCarrierLabel = mStatusBarWindow.findViewById(R.id.keyguard_carrier_text);
+        // TODO: Comment in when transition is ready.
+        //mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
         mStackScroller.addView(mKeyguardIconOverflowContainer);
 
         mExpandedContents = mStackScroller;
@@ -719,8 +734,6 @@
         }
 
         // Quick Settings (where available, some restrictions apply)
-        mNotificationPadding = mContext.getResources()
-                .getDimensionPixelSize(R.dimen.notification_side_padding);
         if (mHasQuickSettings) {
             // Quick Settings needs a container to survive
             mSettingsContainer = (QuickSettingsContainerView)
@@ -785,7 +798,9 @@
         } else if (mSettingsTracker != null && (event.getAction() == MotionEvent.ACTION_UP
                 || event.getAction() == MotionEvent.ACTION_CANCEL)) {
             final float dy = event.getY() - mSettingsDownY;
-            final FlipperButton flipper = mOnKeyguard ? mKeyguardFlipper : mHeaderFlipper;
+            final FlipperButton flipper = mState == StatusBarState.KEYGUARD
+                    ? mKeyguardFlipper
+                    : mHeaderFlipper;
             final boolean inButton = flipper.inHolderBounds(event);
             final boolean qsTap = mSettingsClosing && Math.abs(dy) < slop;
             if (!qsTap && !inButton) {
@@ -1193,7 +1208,7 @@
             }
 
             if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0
-                    && !mNotificationPanel.isTracking() && !mOnKeyguard) {
+                    && !mNotificationPanel.isTracking() && mState != StatusBarState.KEYGUARD) {
                 animateCollapsePanels();
             }
         }
@@ -1347,7 +1362,7 @@
             && mStackScroller.getHeight() < (mNotificationPanel.getHeight()
                     - mCarrierLabelHeight - mNotificationHeaderHeight)
             && mStackScroller.getVisibility() == View.VISIBLE
-            && !mOnKeyguard;
+            && mState != StatusBarState.KEYGUARD;
 
         if (force || mCarrierLabelVisible != makeVisible) {
             mCarrierLabelVisible = makeVisible;
@@ -2098,7 +2113,7 @@
         if (mDemoMode) return;
         int sbMode = mStatusBarMode;
         if (panelsEnabled() && (mInteractingWindows & StatusBarManager.WINDOW_STATUS_BAR) != 0
-                && !mOnKeyguard) {
+                && mState != StatusBarState.KEYGUARD) {
             // if panels are expandable, force the status bar opaque on any interaction
             sbMode = MODE_OPAQUE;
         }
@@ -2211,12 +2226,20 @@
 
     @Override
     public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
-        boolean altBack = (backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS)
-            || ((vis & InputMethodService.IME_VISIBLE) != 0);
+        boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0;
+        int flags = mNavigationIconHints;
+        if ((backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS) || imeShown) {
+            flags |= NAVIGATION_HINT_BACK_ALT;
+        } else {
+            flags &= ~NAVIGATION_HINT_BACK_ALT;
+        }
+        if (imeShown) {
+            flags |= NAVIGATION_HINT_IME_SHOWN;
+        } else {
+            flags &= ~NAVIGATION_HINT_IME_SHOWN;
+        }
 
-        setNavigationIconHints(
-                altBack ? (mNavigationIconHints | NAVIGATION_HINT_BACK_ALT)
-                        : (mNavigationIconHints & ~NAVIGATION_HINT_BACK_ALT));
+        setNavigationIconHints(flags);
         if (mQS != null) mQS.setImeWindowStatus(vis > 0);
     }
 
@@ -2551,12 +2574,14 @@
                 notifyNavigationBarScreenOn(false);
                 notifyHeadsUpScreenOn(false);
                 finishBarAnimations();
+                stopNotificationLogging();
             }
             else if (Intent.ACTION_SCREEN_ON.equals(action)) {
                 mScreenOn = true;
                 // work around problem where mDisplay.getRotation() is not stable while screen is off (bug 7086018)
                 repositionNavigationBar();
                 notifyNavigationBarScreenOn(true);
+                startNotificationLoggingIfScreenOnAndVisible();
             }
             else if (ACTION_DEMO.equals(action)) {
                 Bundle bundle = intent.getExtras();
@@ -2730,22 +2755,40 @@
 
     @Override
     protected void visibilityChanged(boolean visible) {
+        mVisible = visible;
         if (visible) {
-            mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener);
+            startNotificationLoggingIfScreenOnAndVisible();
         } else {
-            // Report all notifications as invisible and turn down the
-            // reporter.
-            if (!mCurrentlyVisibleNotifications.isEmpty()) {
-                logNotificationVisibilityChanges(
-                        Collections.<String>emptyList(), mCurrentlyVisibleNotifications);
-                mCurrentlyVisibleNotifications.clear();
-            }
-            mHandler.removeCallbacks(mVisibilityReporter);
-            mStackScroller.setChildLocationsChangedListener(null);
+            stopNotificationLogging();
         }
         super.visibilityChanged(visible);
     }
 
+    private void stopNotificationLogging() {
+        // Report all notifications as invisible and turn down the
+        // reporter.
+        if (!mCurrentlyVisibleNotifications.isEmpty()) {
+            logNotificationVisibilityChanges(
+                    Collections.<String>emptyList(), mCurrentlyVisibleNotifications);
+            mCurrentlyVisibleNotifications.clear();
+        }
+        mHandler.removeCallbacks(mVisibilityReporter);
+        mStackScroller.setChildLocationsChangedListener(null);
+    }
+
+    private void startNotificationLoggingIfScreenOnAndVisible() {
+        if (mVisible && mScreenOn) {
+            mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener);
+            // Some transitions like mScreenOn=false -> mScreenOn=true don't
+            // cause the scroller to emit child location events. Hence generate
+            // one ourselves to guarantee that we're reporting visible
+            // notifications.
+            // (Note that in cases where the scroller does emit events, this
+            // additional event doesn't break anything.)
+            mNotificationLocationsChangedListener.onChildLocationsChanged(mStackScroller);
+        }
+    }
+
     private void logNotificationVisibilityChanges(
             Collection<String> newlyVisible, Collection<String> noLongerVisible) {
         if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
@@ -2930,28 +2973,38 @@
         }
     }
 
-    public boolean isOnKeyguard() {
-        return mOnKeyguard;
+    /**
+     * @return The {@link StatusBarState} the status bar is in.
+     */
+    public int getBarState() {
+        return mState;
     }
 
     public void showKeyguard() {
-        mOnKeyguard = true;
+        setBarState(StatusBarState.KEYGUARD);
         updateKeyguardState();
         instantExpandNotificationsPanel();
+        mLeaveOpenOnKeyguardHide = false;
     }
 
     public void hideKeyguard() {
-        mOnKeyguard = false;
+        setBarState(StatusBarState.SHADE);
+        if (mLeaveOpenOnKeyguardHide) {
+            mLeaveOpenOnKeyguardHide = false;
+            mNotificationPanel.animateNextTopPaddingChange();
+        } else {
+            instantCollapseNotificationPanel();
+        }
         updateKeyguardState();
-        instantCollapseNotificationPanel();
     }
 
     private void updatePublicMode() {
-        setLockscreenPublicMode(mOnKeyguard && mStatusBarKeyguardViewManager.isSecure());
+        setLockscreenPublicMode(mState == StatusBarState.KEYGUARD
+                && mStatusBarKeyguardViewManager.isSecure());
     }
 
     private void updateKeyguardState() {
-        if (mOnKeyguard) {
+        if (mState == StatusBarState.KEYGUARD) {
             if (isFlippedToSettings()) {
                 flipToNotifications(false /*animate*/);
             }
@@ -2983,17 +3036,17 @@
     }
 
     public void userActivity() {
-        if (mOnKeyguard) {
+        if (mState == StatusBarState.KEYGUARD) {
             mKeyguardViewMediatorCallback.userActivity();
         }
     }
 
     public boolean onMenuPressed() {
-        return mOnKeyguard && mStatusBarKeyguardViewManager.onMenuPressed();
+        return mState == StatusBarState.KEYGUARD && mStatusBarKeyguardViewManager.onMenuPressed();
     }
 
     public boolean onBackPressed() {
-        if (mOnKeyguard) {
+        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
             return mStatusBarKeyguardViewManager.onBackPressed();
         } else {
             animateCollapsePanels();
@@ -3002,7 +3055,7 @@
     }
 
     private void showBouncer() {
-        if (mOnKeyguard) {
+        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
             mStatusBarKeyguardViewManager.dismiss();
         }
     }
@@ -3038,6 +3091,14 @@
         super.onActivated(view);
     }
 
+    /**
+     * @param state The {@link StatusBarState} to set.
+     */
+    public void setBarState(int state) {
+        mState = state;
+        mStatusBarWindowManager.setStatusBarState(state);
+    }
+
     @Override
     public void onReset(View view) {
         super.onReset(view);
@@ -3045,13 +3106,13 @@
     }
 
     public void onTrackingStarted() {
-        if (mOnKeyguard) {
+        if (mState == StatusBarState.KEYGUARD) {
             mKeyguardIndicationTextView.switchIndication(R.string.keyguard_unlock);
         }
     }
 
     public void onTrackingStopped() {
-        if (mOnKeyguard) {
+        if (mState == StatusBarState.KEYGUARD) {
             mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
         }
     }
@@ -3065,6 +3126,67 @@
         return mNavigationBarView;
     }
 
+    // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
+
+    @Override
+    public void onDraggedDown(View startingChild) {
+        goToLockedShade(startingChild);
+    }
+
+    @Override
+    public void onReset() {
+        int n = mNotificationData.size();
+        for (int i = 0; i < n; i++) {
+            NotificationData.Entry entry = mNotificationData.get(i);
+            if (entry.row.getVisibility() != View.GONE) {
+                entry.row.setDimmed(true /* dimmed */, true /* fade */);
+            }
+        }
+        if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
+            mKeyguardIconOverflowContainer.setDimmed(true /* dimmed */, true /* fade */);
+        }
+    }
+
+    public void onThresholdReached() {
+        int n = mNotificationData.size();
+        for (int i = 0; i < n; i++) {
+            NotificationData.Entry entry = mNotificationData.get(i);
+            if (entry.row.getVisibility() != View.GONE) {
+                entry.row.setDimmed(false /* dimmed */, true /* fade */);
+            }
+        }
+        if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
+            mKeyguardIconOverflowContainer.setDimmed(false /* dimmed */, true /* fade */);
+        }
+    }
+
+    /**
+     * If secure with redaction: Show bouncer, go to unlocked shade.
+     *
+     * <p>If secure without redaction: Go to {@link StatusBarState#SHADE_LOCKED}.</p>
+     *
+     * <p>Otherwise go directly to unlocked shade.</p>
+     *
+     * @param expandView The view to expand after going to the shade.
+     */
+    public void goToLockedShade(View expandView) {
+        if (expandView instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) expandView;
+            row.setUserExpanded(true);
+        }
+        if (isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(mCurrentUserId)) {
+            mLeaveOpenOnKeyguardHide = true;
+            showBouncer();
+        } else if (mStatusBarKeyguardViewManager.isSecure()) {
+            mNotificationPanel.animateNextTopPaddingChange();
+            setBarState(StatusBarState.SHADE_LOCKED);
+            updateKeyguardState();
+        } else {
+            mLeaveOpenOnKeyguardHide = true;
+            mStatusBarKeyguardViewManager.dismiss();
+        }
+    }
+
     /**
      * @return a ViewGroup that spans the entire panel which contains the quick settings
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 79c63f7..10c1625 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -19,7 +19,6 @@
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
 import android.util.AttributeSet;
 import android.util.EventLog;
 import android.util.Log;
@@ -29,6 +28,7 @@
 
 import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.StatusBarState;
 
 public class PhoneStatusBarView extends PanelBar {
     private static final String TAG = "PhoneStatusBarView";
@@ -187,7 +187,10 @@
         if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()
                 && mBar.mStatusBarWindow != null) {
             if (mShouldFade) {
-                int scrimColor = mBar.isOnKeyguard() ? mScrimColorKeyguard : mScrimColor;
+                int scrimColor = (mBar.getBarState() == StatusBarState.KEYGUARD
+                        || mBar.getBarState() == StatusBarState.SHADE_LOCKED)
+                        ? mScrimColorKeyguard
+                        : mScrimColor;
                 frac = mPanelExpandedFractionSum; // don't judge me
                 // let's start this 20% of the way down the screen
                 frac = frac * 1.2f - 0.2f;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index c2595cf..e24ddd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -18,22 +18,14 @@
 
 import android.content.Context;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.RemoteException;
-import android.util.Log;
 import android.util.Slog;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
 
 import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardHostView;
-import com.android.keyguard.KeyguardSimpleHostView;
-import com.android.keyguard.R;
 import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.keyguard.KeyguardViewMediator;
 
 /**
  * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
@@ -82,7 +74,7 @@
         mShowing = true;
         mStatusBarWindowManager.setKeyguardShowing(true);
         showBouncerOrKeyguard();
-        updateBackButtonState();
+        updateStates();
     }
 
     /**
@@ -102,9 +94,9 @@
         }
     }
 
-    public void showBouncer() {
+    private void showBouncer() {
         mBouncer.show();
-        updateBackButtonState();
+        updateStates();
     }
 
     /**
@@ -112,7 +104,7 @@
      */
     public void reset() {
         showBouncerOrKeyguard();
-        updateBackButtonState();
+        updateStates();
     }
 
     public void onScreenTurnedOff() {
@@ -155,7 +147,7 @@
     public void setOccluded(boolean occluded) {
         mOccluded = occluded;
         mStatusBarWindowManager.setKeyguardOccluded(occluded);
-        updateBackButtonState();
+        updateStates();
     }
 
     /**
@@ -167,7 +159,7 @@
         mStatusBarWindowManager.setKeyguardShowing(false);
         mBouncer.hide();
         mViewMediatorCallback.keyguardGone();
-        updateBackButtonState();
+        updateStates();
     }
 
     /**
@@ -199,13 +191,13 @@
         if (mBouncer.isShowing()) {
             mBouncer.hide();
             mPhoneStatusBar.showKeyguard();
-            updateBackButtonState();
+            updateStates();
             return true;
         }
         return false;
     }
 
-    private void updateBackButtonState() {
+    private void updateStates() {
         int vis = mContainer.getSystemUiVisibility();
         boolean bouncerDismissable = mBouncer.isShowing() && !mBouncer.needsFullscreenBouncer();
         if (bouncerDismissable || !mShowing) {
@@ -213,11 +205,14 @@
         } else {
             mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
         }
-        if (!(mShowing && !mOccluded) || mBouncer.isShowing()) {
-            mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
-        } else {
-            mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
+        if (mPhoneStatusBar.getNavigationBarView() != null) {
+            if (!(mShowing && !mOccluded) || mBouncer.isShowing()) {
+                mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
+            } else {
+                mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
+            }
         }
+        mPhoneStatusBar.setBouncerShowing(mBouncer.isShowing());
     }
 
     public boolean onMenuPressed() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index d175d7a..a4c9df5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.app.ActionBar;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Resources;
@@ -28,6 +27,8 @@
 import android.view.WindowManager;
 
 import com.android.keyguard.R;
+import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.StatusBarState;
 
 /**
  * Encapsulates all logic for the status bar window state management.
@@ -137,7 +138,8 @@
     }
 
     private void applyUserActivityTimeout(State state) {
-        if (state.isKeyguardShowingAndNotOccluded()) {
+        if (state.isKeyguardShowingAndNotOccluded()
+                && state.statusBarState == StatusBarState.KEYGUARD) {
             mLp.userActivityTimeout = state.keyguardUserActivityTimeout;
         } else {
             mLp.userActivityTimeout = -1;
@@ -145,7 +147,8 @@
     }
 
     private void applyInputFeatures(State state) {
-        if (state.isKeyguardShowingAndNotOccluded()) {
+        if (state.isKeyguardShowingAndNotOccluded()
+                && state.statusBarState == StatusBarState.KEYGUARD) {
             mLp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
         } else {
             mLp.inputFeatures &= ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
@@ -194,6 +197,14 @@
         apply(mCurrentState);
     }
 
+    /**
+     * @param state The {@link StatusBarState} of the status bar.
+     */
+    public void setStatusBarState(int state) {
+        mCurrentState.statusBarState = state;
+        apply(mCurrentState);
+    }
+
     private static class State {
         boolean keyguardShowing;
         boolean keyguardOccluded;
@@ -202,6 +213,11 @@
         boolean statusBarFocusable;
         long keyguardUserActivityTimeout;
 
+        /**
+         * The {@link BaseStatusBar} state from the status bar.
+         */
+        int statusBarState;
+
         private boolean isKeyguardShowingAndNotOccluded() {
             return keyguardShowing && !keyguardOccluded;
         }
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 6b5ef5a..acc3a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -31,16 +31,17 @@
 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.DragDownHelper;
+import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 
-public class StatusBarWindowView extends FrameLayout
-{
+public class StatusBarWindowView extends FrameLayout {
     public static final String TAG = "StatusBarWindowView";
     public static final boolean DEBUG = BaseStatusBar.DEBUG;
 
     private ExpandHelper mExpandHelper;
+    private DragDownHelper mDragDownHelper;
     private NotificationStackScrollLayout mStackScrollLayout;
     private NotificationPanelView mNotificationPanel;
 
@@ -75,6 +76,7 @@
                 minHeight, maxHeight);
         mExpandHelper.setEventSource(this);
         mExpandHelper.setScrollAdapter(mStackScrollLayout);
+        mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
 
         // We really need to be able to animate while window animations are going on
         // so that activities may be started asynchronously from panel animations
@@ -106,8 +108,13 @@
         boolean intercept = false;
         if (mNotificationPanel.isFullyExpanded()
                 && mStackScrollLayout.getVisibility() == View.VISIBLE
-                && !mService.isOnKeyguard()) {
+                && mService.getBarState() != StatusBarState.KEYGUARD) {
             intercept = mExpandHelper.onInterceptTouchEvent(ev);
+        } else if (mNotificationPanel.isFullyExpanded()
+                && mStackScrollLayout.getVisibility() == View.VISIBLE
+                && mService.getBarState() == StatusBarState.KEYGUARD
+                && !mService.isBouncerShowing()) {
+            intercept = mDragDownHelper.onInterceptTouchEvent(ev);
         }
         if (!intercept) {
             super.onInterceptTouchEvent(ev);
@@ -124,8 +131,11 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         boolean handled = false;
-        if (mNotificationPanel.isFullyExpanded()) {
+        if (mNotificationPanel.isFullyExpanded()
+                && mService.getBarState() != StatusBarState.KEYGUARD) {
             handled = mExpandHelper.onTouchEvent(ev);
+        } else if (mService.getBarState() == StatusBarState.KEYGUARD) {
+            handled = mDragDownHelper.onTouchEvent(ev);
         }
         if (!handled) {
             handled = super.onTouchEvent(ev);
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 20011ff..ff921cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -356,7 +356,7 @@
 
         @Override
         public boolean onTouchEvent(MotionEvent event) {
-            log("onTouchEvent " + MotionEvent.actionToString(event.getAction()));
+            if (DEBUG) log("onTouchEvent " + MotionEvent.actionToString(event.getAction()));
             if (event.getAction() == MotionEvent.ACTION_DOWN) {
                 mDownX = event.getX();
             } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
index 1bc97a0..8748888 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
@@ -58,7 +58,7 @@
         mNoMan = INotificationManager.Stub.asInterface(
                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
         try {
-            mNoMan.requestZenModeConditions(mListener, true /*requested*/);
+            mNoMan.requestZenModeConditions(mListener, Condition.FLAG_RELEVANT_NOW);
         } catch (RemoteException e) {
             // noop
         }
@@ -98,7 +98,7 @@
     @Override
     public void dispose() {
         try {
-            mNoMan.requestZenModeConditions(mListener, false /*requested*/);
+            mNoMan.requestZenModeConditions(mListener, 0 /*none*/);
         } catch (RemoteException e) {
             // noop
         }
@@ -222,7 +222,7 @@
                 mExits.remove(i);
             }
             for (Condition c : mConditions.values()) {
-                mExits.add(newExit(c.caption, "", "", c.id));
+                mExits.add(newExit(c.summary, c.line1, c.line2, c.id));
             }
             dispatchChanged();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index c94c65f..72e22e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -32,6 +32,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.NotificationData;
 
 public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.Callback, ExpandHelper.Callback {
@@ -185,12 +186,12 @@
     // ExpandHelper.Callback methods
 
     @Override
-    public View getChildAtRawPosition(float x, float y) {
+    public ExpandableView getChildAtRawPosition(float x, float y) {
         return getChildAtPosition(x, y);
     }
 
     @Override
-    public View getChildAtPosition(float x, float y) {
+    public ExpandableView getChildAtPosition(float x, float y) {
         return mHeadsUp == null ? null : mHeadsUp.row;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
deleted file mode 100644
index 266cecf..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.animation.LayoutTransition;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-
-import com.android.systemui.ExpandHelper;
-import com.android.systemui.R;
-import com.android.systemui.SwipeHelper;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-
-import java.util.HashMap;
-
-public class NotificationRowLayout
-        extends LinearLayout
-        implements SwipeHelper.Callback, ExpandHelper.Callback
-{
-    private static final String TAG = "NotificationRowLayout";
-    private static final boolean DEBUG = false;
-    private static final boolean SLOW_ANIMATIONS = DEBUG;
-
-    private static final int APPEAR_ANIM_LEN = SLOW_ANIMATIONS ? 5000 : 250;
-    private static final int DISAPPEAR_ANIM_LEN = APPEAR_ANIM_LEN;
-
-    boolean mAnimateBounds = true;
-
-    Rect mTmpRect = new Rect();
-
-    HashMap<View, ValueAnimator> mAppearingViews = new HashMap<View, ValueAnimator>();
-    HashMap<View, ValueAnimator> mDisappearingViews = new HashMap<View, ValueAnimator>();
-
-    private SwipeHelper mSwipeHelper;
-
-    private OnSizeChangedListener mOnSizeChangedListener;
-
-    // Flag set during notification removal animation to avoid causing too much work until
-    // animation is done
-    boolean mRemoveViews = true;
-
-    private LayoutTransition mRealLayoutTransition;
-
-    public NotificationRowLayout(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public NotificationRowLayout(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        mRealLayoutTransition = new LayoutTransition();
-        mRealLayoutTransition.setAnimateParentHierarchy(true);
-        setLayoutTransitionsEnabled(true);
-
-        setOrientation(LinearLayout.VERTICAL);
-
-        if (DEBUG) {
-            setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
-                @Override
-                public void onChildViewAdded(View parent, View child) {
-                    Log.d(TAG, "view added: " + child + "; new count: " + getChildCount());
-                }
-                @Override
-                public void onChildViewRemoved(View parent, View child) {
-                    Log.d(TAG, "view removed: " + child + "; new count: " + (getChildCount() - 1));
-                }
-            });
-
-            setBackgroundColor(0x80FF8000);
-        }
-
-        float densityScale = getResources().getDisplayMetrics().density;
-        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
-        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
-    }
-
-    public void setLongPressListener(View.OnLongClickListener listener) {
-        mSwipeHelper.setLongPressListener(listener);
-    }
-
-    public void setOnSizeChangedListener(OnSizeChangedListener l) {
-        mOnSizeChangedListener = l;
-    }
-
-    @Override
-    public void onWindowFocusChanged(boolean hasWindowFocus) {
-        super.onWindowFocusChanged(hasWindowFocus);
-        if (!hasWindowFocus) {
-            mSwipeHelper.removeLongPressCallback();
-        }
-    }
-
-    public void setAnimateBounds(boolean anim) {
-        mAnimateBounds = anim;
-    }
-
-    private void logLayoutTransition() {
-        Log.v(TAG, "layout " +
-              (mRealLayoutTransition.isChangingLayout() ? "is " : "is not ") +
-              "in transition and animations " +
-              (mRealLayoutTransition.isRunning() ? "are " : "are not ") +
-              "running.");
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()");
-        if (DEBUG) logLayoutTransition();
-
-        return mSwipeHelper.onInterceptTouchEvent(ev) ||
-                super.onInterceptTouchEvent(ev);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        if (DEBUG) Log.v(TAG, "onTouchEvent()");
-        if (DEBUG) logLayoutTransition();
-
-        return mSwipeHelper.onTouchEvent(ev) ||
-                super.onTouchEvent(ev);
-    }
-
-    public boolean canChildBeDismissed(View v) {
-        final View veto = v.findViewById(R.id.veto);
-        return (veto != null && veto.getVisibility() != View.GONE);
-    }
-
-    public boolean canChildBeExpanded(View v) {
-        return v instanceof ExpandableNotificationRow
-                && ((ExpandableNotificationRow) v).isExpandable();
-    }
-
-    public void setUserExpandedChild(View v, boolean userExpanded) {
-        if (v instanceof ExpandableNotificationRow) {
-            ((ExpandableNotificationRow) v).setUserExpanded(userExpanded);
-        }
-    }
-
-    public void setUserLockedChild(View v, boolean userLocked) {
-        if (v instanceof ExpandableNotificationRow) {
-            ((ExpandableNotificationRow) v).setUserLocked(userLocked);
-        }
-    }
-
-    public void onChildDismissed(View v) {
-        if (DEBUG) Log.v(TAG, "onChildDismissed: " + v + " mRemoveViews=" + mRemoveViews);
-        final View veto = v.findViewById(R.id.veto);
-        if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {
-            veto.performClick();
-        }
-    }
-
-    public void onBeginDrag(View v) {
-        // We need to prevent the surrounding ScrollView from intercepting us now;
-        // the scroll position will be locked while we swipe
-        requestDisallowInterceptTouchEvent(true);
-    }
-
-    public void onDragCancelled(View v) {
-    }
-
-    public View getChildAtPosition(MotionEvent ev) {
-        return getChildAtPosition(ev.getX(), ev.getY());
-    }
-
-    public View getChildAtRawPosition(float touchX, float touchY) {
-        int[] location = new int[2];
-        getLocationOnScreen(location);
-        return getChildAtPosition((float) (touchX - location[0]), (float) (touchY - location[1]));
-    }
-
-    public View getChildAtPosition(float touchX, float touchY) {
-        // find the view under the pointer, accounting for GONE views
-        final int count = getChildCount();
-        int y = 0;
-        int childIdx = 0;
-        View slidingChild;
-        for (; childIdx < count; childIdx++) {
-            slidingChild = getChildAt(childIdx);
-            if (slidingChild.getVisibility() == GONE) {
-                continue;
-            }
-            y += slidingChild.getMeasuredHeight();
-            if (touchY < y) return slidingChild;
-        }
-        return null;
-    }
-
-    public View getChildContentView(View v) {
-        return v;
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        float densityScale = getResources().getDisplayMetrics().density;
-        mSwipeHelper.setDensityScale(densityScale);
-        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
-        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
-    }
-
-
-    /**
-     * Sets a flag to tell us whether to actually remove views. Removal is delayed by setting this
-     * to false during some animations to smooth out performance. Callers should restore the
-     * flag to true after the animation is done, and then they should make sure that the views
-     * get removed properly.
-     */
-    public void setViewRemoval(boolean removeViews) {
-        if (DEBUG) Log.v(TAG, "setViewRemoval: " + removeViews);
-        mRemoveViews = removeViews;
-    }
-
-    // Suppress layout transitions for a little while.
-    public void setLayoutTransitionsEnabled(boolean b) {
-        if (b) {
-            setLayoutTransition(mRealLayoutTransition);
-        } else {
-            if (mRealLayoutTransition.isRunning()) {
-                mRealLayoutTransition.cancel();
-            }
-            setLayoutTransition(null);
-        }
-    }
-
-    public void dismissRowAnimated(View child) {
-        dismissRowAnimated(child, 0);
-    }
-
-    public void dismissRowAnimated(View child, int vel) {
-        mSwipeHelper.dismissChild(child, vel);
-    }
-
-    @Override
-    public void onFinishInflate() {
-        super.onFinishInflate();
-        if (DEBUG) setWillNotDraw(false);
-    }
-
-    @Override
-    public void onDraw(android.graphics.Canvas c) {
-        super.onDraw(c);
-        if (DEBUG) logLayoutTransition();
-        if (DEBUG) {
-            //Log.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: "
-            //        + getMeasuredHeight() + "px");
-            c.save();
-            c.clipRect(6, 6, c.getWidth() - 6, getMeasuredHeight() - 6,
-                    android.graphics.Region.Op.DIFFERENCE);
-            c.drawColor(0xFFFF8000);
-            c.restore();
-        }
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        if (mOnSizeChangedListener != null) {
-            mOnSizeChangedListener.onSizeChanged(this, w, h, oldw, oldh);
-        }
-    }
-}
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 2e30594..e4e5fb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -83,6 +83,7 @@
     private int mBottomStackPeekSize;
     private int mEmptyMarginBottom;
     private int mPaddingBetweenElements;
+    private int mTopPadding;
     private boolean mListenForHeightChanges = true;
 
     /**
@@ -96,21 +97,23 @@
     private StackScrollState mCurrentStackScrollState = new StackScrollState(this);
     private ArrayList<View> mChildrenToAddAnimated = new ArrayList<View>();
     private ArrayList<View> mChildrenToRemoveAnimated = new ArrayList<View>();
-    private ArrayList<ChildHierarchyChangeEvent> mAnimationEvents
-            = new ArrayList<ChildHierarchyChangeEvent>();
+    private ArrayList<AnimationEvent> mAnimationEvents
+            = new ArrayList<AnimationEvent>();
     private ArrayList<View> mSwipedOutViews = new ArrayList<View>();
     private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
 
     private OnChildLocationsChangedListener mListener;
     private ExpandableView.OnHeightChangedListener mOnHeightChangedListener;
-    private boolean mChildHierarchyDirty;
+    private boolean mNeedsAnimation;
+    private boolean mTopPaddingNeedsAnimation;
     private boolean mIsExpanded = true;
-    private ViewTreeObserver.OnPreDrawListener mAfterLayoutPreDrawListener
+    private boolean mChildrenUpdateRequested;
+    private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
             = new ViewTreeObserver.OnPreDrawListener() {
         @Override
         public boolean onPreDraw() {
-            updateScrollPositionIfNecessary();
             updateChildren();
+            mChildrenUpdateRequested = false;
             getViewTreeObserver().removeOnPreDrawListener(this);
             return true;
         }
@@ -157,6 +160,7 @@
         mScroller = new OverScroller(getContext());
         setFocusable(true);
         setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
+        setClipChildren(false);
         final ViewConfiguration configuration = ViewConfiguration.get(context);
         mTouchSlop = configuration.getScaledTouchSlop();
         mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
@@ -205,7 +209,8 @@
         }
         setMaxLayoutHeight(getHeight() - mEmptyMarginBottom);
         updateContentHeight();
-        getViewTreeObserver().addOnPreDrawListener(mAfterLayoutPreDrawListener);
+        updateScrollPositionIfNecessary();
+        requestChildrenUpdate();
     }
 
     public void setChildLocationsChangedListener(OnChildLocationsChangedListener listener) {
@@ -228,11 +233,31 @@
 
     private void setMaxLayoutHeight(int maxLayoutHeight) {
         mMaxLayoutHeight = maxLayoutHeight;
-        updateAlgorithmHeight();
+        updateAlgorithmHeightAndPadding();
     }
 
-    private void updateAlgorithmHeight() {
+    private void updateAlgorithmHeightAndPadding() {
         mStackScrollAlgorithm.setLayoutHeight(getLayoutHeight());
+        mStackScrollAlgorithm.setTopPadding(mTopPadding);
+    }
+
+    /**
+     * @return whether the height of the layout needs to be adapted, in order to ensure that the
+     *         last child is not in the bottom stack.
+     */
+    private boolean needsHeightAdaption() {
+        View lastChild = getLastChildNotGone();
+        View firstChild = getFirstChildNotGone();
+        boolean isLastChildExpanded = isViewExpanded(lastChild);
+        return isLastChildExpanded && lastChild != firstChild;
+    }
+
+    private boolean isViewExpanded(View view) {
+        if (view != null) {
+            ExpandableView expandView = (ExpandableView) view;
+            return expandView.getActualHeight() > mCollapsedSize;
+        }
+        return false;
     }
 
     /**
@@ -242,13 +267,18 @@
     private void updateChildren() {
         mCurrentStackScrollState.setScrollY(mOwnScrollY);
         mStackScrollAlgorithm.getStackScrollState(mCurrentStackScrollState);
-        if (!isCurrentlyAnimating() && !mChildHierarchyDirty) {
+        if (!isCurrentlyAnimating() && !mNeedsAnimation) {
             applyCurrentState();
-            if (mListener != null) {
-                mListener.onChildLocationsChanged(this);
-            }
         } else {
-            startAnimationToState(mCurrentStackScrollState);
+            startAnimationToState();
+        }
+    }
+
+    private void requestChildrenUpdate() {
+        if (!mChildrenUpdateRequested) {
+            getViewTreeObserver().addOnPreDrawListener(mChildrenUpdater);
+            mChildrenUpdateRequested = true;
+            invalidate();
         }
     }
 
@@ -263,10 +293,59 @@
         }
     }
 
-    public void setCurrentStackHeight(int currentStackHeight) {
-        this.mCurrentStackHeight = currentStackHeight;
-        updateAlgorithmHeight();
-        updateChildren();
+    public int getTopPadding() {
+        return mTopPadding;
+    }
+
+    public void setTopPadding(int topPadding, boolean animate) {
+        if (mTopPadding != topPadding) {
+            mTopPadding = topPadding;
+            updateAlgorithmHeightAndPadding();
+            updateContentHeight();
+            if (animate) {
+                mTopPaddingNeedsAnimation = true;
+                mNeedsAnimation =  true;
+            }
+            requestChildrenUpdate();
+            if (mOnHeightChangedListener != null) {
+                mOnHeightChangedListener.onHeightChanged(null);
+            }
+        }
+    }
+
+    /**
+     * Update the height of the stack to a new height.
+     *
+     * @param height the new height of the stack
+     */
+    public void setStackHeight(float height) {
+        setIsExpanded(height > 0.0f);
+        int newStackHeight = (int) height;
+        int itemHeight = getItemHeight();
+        int bottomStackPeekSize = mBottomStackPeekSize;
+        int minStackHeight = itemHeight + bottomStackPeekSize;
+        int stackHeight;
+        if (newStackHeight - mTopPadding >= minStackHeight) {
+            setTranslationY(0);
+            stackHeight = 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 - mTopPadding) / minStackHeight;
+            partiallyThere = Math.max(0, partiallyThere);
+            translationY += (1 - partiallyThere) * bottomStackPeekSize;
+            setTranslationY(translationY - mTopPadding);
+            stackHeight = (int) (height - (translationY - mTopPadding));
+        }
+        if (stackHeight != mCurrentStackHeight) {
+            mCurrentStackHeight = stackHeight;
+            updateAlgorithmHeightAndPadding();
+            requestChildrenUpdate();
+        }
     }
 
     /**
@@ -313,13 +392,13 @@
         return getChildAtPosition(ev.getX(), ev.getY());
     }
 
-    public View getChildAtRawPosition(float touchX, float touchY) {
+    public ExpandableView getChildAtRawPosition(float touchX, float touchY) {
         int[] location = new int[2];
         getLocationOnScreen(location);
-        return getChildAtPosition(touchX - location[0],touchY - location[1]);
+        return getChildAtPosition(touchX - location[0], touchY - location[1]);
     }
 
-    public View getChildAtPosition(float touchX, float touchY) {
+    public ExpandableView getChildAtPosition(float touchX, float touchY) {
         // find the view under the pointer, accounting for GONE views
         final int count = getChildCount();
         for (int childIdx = 0; childIdx < count; childIdx++) {
@@ -599,19 +678,13 @@
         }
     }
 
-    public void customScrollBy(int y) {
-        mOwnScrollY += y;
-        updateChildren();
-    }
-
-    public void customScrollTo(int y) {
+    private void customScrollTo(int y) {
         mOwnScrollY = y;
         updateChildren();
     }
 
     @Override
-    protected void onOverScrolled(int scrollX, int scrollY,
-                                  boolean clampedX, boolean clampedY) {
+    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
         // Treat animating scrolls differently; see #computeScroll() for why.
         if (!mScroller.isFinished()) {
             final int oldX = mScrollX;
@@ -638,7 +711,13 @@
             int firstChildMaxExpandHeight = getMaxExpandHeight(firstChild);
 
             scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
-            if (scrollRange > 0 && getChildCount() > 0) {
+            if (scrollRange > 0) {
+                View lastChild = getLastChildNotGone();
+                if (isViewExpanded(lastChild)) {
+                    // last child is expanded, so we have to ensure that it can exit the
+                    // bottom stack
+                    scrollRange += mCollapsedSize + mPaddingBetweenElements;
+                }
                 // We want to at least be able collapse the first item and not ending in a weird
                 // end state.
                 scrollRange = Math.max(scrollRange, firstChildMaxExpandHeight - mCollapsedSize);
@@ -661,10 +740,24 @@
         return null;
     }
 
+    /**
+     * @return the last child which has visibility unequal to GONE
+     */
+    private View getLastChildNotGone() {
+        int childCount = getChildCount();
+        for (int i = childCount - 1; i >= 0; i--) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE) {
+                return child;
+            }
+        }
+        return null;
+    }
+
     private int getMaxExpandHeight(View view) {
         if (view instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-            return row.getMaximumAllowedExpandHeight();
+            return row.getIntrinsicHeight();
         }
         return view.getHeight();
     }
@@ -684,14 +777,14 @@
                 }
                 if (child instanceof ExpandableNotificationRow) {
                     ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                    height += row.getMaximumAllowedExpandHeight();
+                    height += row.getIntrinsicHeight();
                 } else if (child instanceof ExpandableView) {
                     ExpandableView expandableView = (ExpandableView) child;
                     height += expandableView.getActualHeight();
                 }
             }
         }
-        mContentHeight = height;
+        mContentHeight = height + mTopPadding;
     }
 
     /**
@@ -748,9 +841,13 @@
         updateScrollStateForRemovedChild(child);
         if (mIsExpanded) {
 
-            // Generate Animations
-            mChildrenToRemoveAnimated.add(child);
-            mChildHierarchyDirty = true;
+            if (!mChildrenToAddAnimated.contains(child)) {
+                // Generate Animations
+                mChildrenToRemoveAnimated.add(child);
+                mNeedsAnimation = true;
+            } else {
+                mChildrenToAddAnimated.remove(child);
+            }
         }
     }
 
@@ -806,7 +903,7 @@
 
             // Generate Animations
             mChildrenToAddAnimated.add(child);
-            mChildHierarchyDirty = true;
+            mNeedsAnimation = true;
         }
     }
 
@@ -822,27 +919,32 @@
         }
     }
 
-    private void startAnimationToState(StackScrollState finalState) {
-        if (mChildHierarchyDirty) {
+    private void startAnimationToState() {
+        if (mNeedsAnimation) {
             generateChildHierarchyEvents();
-            mChildHierarchyDirty = false;
+            mNeedsAnimation = false;
         }
-        mStateAnimator.startAnimationForEvents(mAnimationEvents, finalState);
+        if (!mAnimationEvents.isEmpty()) {
+            mStateAnimator.startAnimationForEvents(mAnimationEvents, mCurrentStackScrollState);
+        } else {
+            applyCurrentState();
+        }
     }
 
     private void generateChildHierarchyEvents() {
         generateChildAdditionEvents();
         generateChildRemovalEvents();
-        mChildHierarchyDirty = false;
+        generateTopPaddingEvent();
+        mNeedsAnimation = false;
     }
 
     private void generateChildRemovalEvents() {
         for (View  child : mChildrenToRemoveAnimated) {
             boolean childWasSwipedOut = mSwipedOutViews.contains(child);
             int animationType = childWasSwipedOut
-                    ? ChildHierarchyChangeEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
-                    : ChildHierarchyChangeEvent.ANIMATION_TYPE_REMOVE;
-            mAnimationEvents.add(new ChildHierarchyChangeEvent(child, animationType));
+                    ? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
+                    : AnimationEvent.ANIMATION_TYPE_REMOVE;
+            mAnimationEvents.add(new AnimationEvent(child, animationType));
         }
         mSwipedOutViews.clear();
         mChildrenToRemoveAnimated.clear();
@@ -850,12 +952,20 @@
 
     private void generateChildAdditionEvents() {
         for (View  child : mChildrenToAddAnimated) {
-            mAnimationEvents.add(new ChildHierarchyChangeEvent(child,
-                    ChildHierarchyChangeEvent.ANIMATION_TYPE_ADD));
+            mAnimationEvents.add(new AnimationEvent(child,
+                    AnimationEvent.ANIMATION_TYPE_ADD));
         }
         mChildrenToAddAnimated.clear();
     }
 
+    private void generateTopPaddingEvent() {
+        if (mTopPaddingNeedsAnimation) {
+            mAnimationEvents.add(
+                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_TOP_PADDING_CHANGED));
+        }
+        mTopPaddingNeedsAnimation = false;
+    }
+
     private boolean onInterceptTouchEventScroll(MotionEvent ev) {
         /*
          * This method JUST determines whether we want to intercept the motion.
@@ -996,7 +1106,11 @@
     }
 
     public int getEmptyBottomMargin() {
-        return Math.max(getHeight() - mContentHeight, 0);
+        int emptyMargin = mMaxLayoutHeight - mContentHeight;
+        if (needsHeightAdaption()) {
+            emptyMargin = emptyMargin - mCollapsedSize - mBottomStackPeekSize;
+        }
+        return Math.max(emptyMargin, 0);
     }
 
     public void onExpansionStarted() {
@@ -1007,7 +1121,7 @@
         mStackScrollAlgorithm.onExpansionStopped();
     }
 
-    public void setIsExpanded(boolean isExpanded) {
+    private void setIsExpanded(boolean isExpanded) {
         mIsExpanded = isExpanded;
         mStackScrollAlgorithm.setIsExpanded(isExpanded);
         if (!isExpanded) {
@@ -1023,7 +1137,7 @@
             if (mOnHeightChangedListener != null) {
                 mOnHeightChangedListener.onHeightChanged(view);
             }
-            updateChildren();
+            requestChildrenUpdate();
         }
     }
 
@@ -1033,7 +1147,7 @@
     }
 
     public void onChildAnimationFinished() {
-        applyCurrentState();
+        requestChildrenUpdate();
         mAnimationEvents.clear();
     }
 
@@ -1041,6 +1155,9 @@
         mListenForHeightChanges = false;
         mCurrentStackScrollState.apply();
         mListenForHeightChanges = true;
+        if (mListener != null) {
+            mListener.onChildLocationsChanged(this);
+        }
     }
 
     /**
@@ -1050,16 +1167,18 @@
         public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout);
     }
 
-    static class ChildHierarchyChangeEvent {
+    static class AnimationEvent {
 
         static int ANIMATION_TYPE_ADD = 1;
         static int ANIMATION_TYPE_REMOVE = 2;
         static int ANIMATION_TYPE_REMOVE_SWIPED_OUT = 3;
+        static int ANIMATION_TYPE_TOP_PADDING_CHANGED = 4;
+
         final long eventStartTime;
         final View changingView;
         final int animationType;
 
-        ChildHierarchyChangeEvent(View view, int type) {
+        AnimationEvent(View view, int type) {
             eventStartTime = AnimationUtils.currentAnimationTimeMillis();
             changingView = view;
             animationType = type;
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 acd1c6a..09d8d50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -50,6 +50,10 @@
     private StackIndentationFunctor mBottomStackIndentationFunctor;
 
     private int mLayoutHeight;
+
+    /** mLayoutHeight - mTopPadding */
+    private int mInnerHeight;
+    private int mTopPadding;
     private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
     private boolean mIsExpansionChanging;
     private int mFirstChildMaxHeight;
@@ -144,7 +148,7 @@
             StackScrollAlgorithmState algorithmState) {
 
         // The starting position of the bottom stack peek
-        float bottomPeekStart = mLayoutHeight - mBottomStackPeekSize;
+        float bottomPeekStart = mInnerHeight - mBottomStackPeekSize;
 
         // The position where the bottom stack starts.
         float bottomStackStart = bottomPeekStart - mCollapsedSize;
@@ -188,7 +192,7 @@
                 clampYTranslation(childViewState, childHeight);
                 // check if we are overlapping with the bottom stack
                 if (childViewState.yTranslation + childHeight + mPaddingBetweenElements
-                        >= bottomStackStart && !mIsExpansionChanging) {
+                        >= bottomStackStart && !mIsExpansionChanging && i != 0) {
                     // TODO: handle overlapping sizes with end stack better
                     // we just collapse this element
                     childViewState.height = mCollapsedSize;
@@ -226,6 +230,8 @@
             }
             currentYPosition = childViewState.yTranslation + childHeight + mPaddingBetweenElements;
             yPositionInScrollView = yPositionInScrollViewAfterElement;
+
+            childViewState.yTranslation += mTopPadding;
         }
     }
 
@@ -250,7 +256,7 @@
     private void clampPositionToBottomStackStart(StackScrollState.ViewState childViewState,
             int childHeight) {
         childViewState.yTranslation = Math.min(childViewState.yTranslation,
-                mLayoutHeight - mBottomStackPeekSize - childHeight);
+                mInnerHeight - mBottomStackPeekSize - childHeight);
     }
 
     /**
@@ -269,7 +275,7 @@
     private int getMaxAllowedChildHeight(View child) {
         if (child instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            return row.getMaximumAllowedExpandHeight();
+            return row.getIntrinsicHeight();
         } else if (child instanceof ExpandableView) {
             ExpandableView expandableView = (ExpandableView) child;
             return expandableView.getActualHeight();
@@ -318,7 +324,7 @@
                 childViewState.alpha = 1.0f - algorithmState.partialInBottom;
             }
             childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_HIDDEN;
-            currentYPosition = mLayoutHeight;
+            currentYPosition = mInnerHeight;
         }
         childViewState.yTranslation = currentYPosition - childHeight;
         clampPositionToTopStackEnd(childViewState, childHeight);
@@ -396,7 +402,7 @@
                 if (i == 0 && algorithmState.scrollY == mCollapsedSize) {
 
                     // The starting position of the bottom stack peek
-                    int bottomPeekStart = mLayoutHeight - mBottomStackPeekSize;
+                    int bottomPeekStart = mInnerHeight - mBottomStackPeekSize;
                     // Collapse and expand the first child while the shade is being expanded
                     float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
                             ? mFirstChildMaxHeight
@@ -475,12 +481,18 @@
         }
     }
 
-    public int getLayoutHeight() {
-        return mLayoutHeight;
-    }
-
     public void setLayoutHeight(int layoutHeight) {
         this.mLayoutHeight = layoutHeight;
+        updateInnerHeight();
+    }
+
+    public void setTopPadding(int topPadding) {
+        mTopPadding = topPadding;
+        updateInnerHeight();
+    }
+
+    private void updateInnerHeight() {
+        mInnerHeight = mLayoutHeight - mTopPadding;
     }
 
     public void onExpansionStarted(StackScrollState currentState) {
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 8c75adc..26cef36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -71,7 +71,7 @@
                 mStateMap.put(child, viewState);
             }
             // initialize with the default values of the view
-            viewState.height = child.getActualHeight();
+            viewState.height = child.getIntrinsicHeight();
             viewState.gone = child.getVisibility() == View.GONE;
             viewState.alpha = 1;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 9c6238f..4dce288 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.stack;
 
-import android.animation.Animator;
 import android.animation.ValueAnimator;
 import android.view.View;
 import android.view.animation.AnimationUtils;
@@ -35,7 +34,7 @@
     private final Interpolator mFastOutSlowInInterpolator;
     public NotificationStackScrollLayout mHostLayout;
     private boolean mAnimationIsRunning;
-    private ArrayList<NotificationStackScrollLayout.ChildHierarchyChangeEvent> mHandledEvents =
+    private ArrayList<NotificationStackScrollLayout.AnimationEvent> mHandledEvents =
             new ArrayList<>();
 
     public StackStateAnimator(NotificationStackScrollLayout hostLayout) {
@@ -49,7 +48,7 @@
     }
 
     public void startAnimationForEvents(
-            ArrayList<NotificationStackScrollLayout.ChildHierarchyChangeEvent> mAnimationEvents,
+            ArrayList<NotificationStackScrollLayout.AnimationEvent> mAnimationEvents,
             StackScrollState finalState) {
         int numEvents = mAnimationEvents.size();
         if (numEvents == 0) {
@@ -66,8 +65,8 @@
         }
         initializeAddedViewStates(mAnimationEvents, finalState);
         int childCount = mHostLayout.getChildCount();
+        boolean isFirstAnimatingView = true;
         for (int i = 0; i < childCount; i++) {
-            final boolean isFirstView = i == 0;
             final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
             StackScrollState.ViewState viewState = finalState.getViewStateForView(child);
             if (viewState == null) {
@@ -80,7 +79,7 @@
                 child.setVisibility(View.VISIBLE);
             }
 
-            startPropertyAnimation(newDuration, isFirstView, child, viewState, alpha);
+            startPropertyAnimation(newDuration, isFirstAnimatingView, child, viewState, alpha);
 
             // TODO: animate clipBounds
             child.setClipBounds(null);
@@ -88,14 +87,14 @@
             if (viewState.height != currentHeigth) {
                 startHeightAnimation(newDuration, child, viewState, currentHeigth);
             }
+            isFirstAnimatingView = false;
         }
         mAnimationIsRunning = true;
     }
 
-    private void startPropertyAnimation(long newDuration, final boolean isFirstView,
+    private void startPropertyAnimation(long newDuration, final boolean hasFinishAction,
             final ExpandableView child, StackScrollState.ViewState viewState, final float alpha) {
         child.animate().setInterpolator(mFastOutSlowInInterpolator)
-                .alpha(alpha)
                 .translationY(viewState.yTranslation)
                 .translationZ(viewState.zTranslation)
                 .setDuration(newDuration)
@@ -103,7 +102,7 @@
                     @Override
                     public void run() {
                         mAnimationIsRunning = false;
-                        if (isFirstView) {
+                        if (hasFinishAction) {
                             mHandledEvents.clear();
                             mHostLayout.onChildAnimationFinished();
                         }
@@ -112,6 +111,9 @@
                         }
                     }
                 });
+        if (alpha != child.getAlpha()) {
+            child.animate().withLayer().alpha(alpha);
+        }
     }
 
     private void startHeightAnimation(long newDuration, final ExpandableView child,
@@ -128,16 +130,26 @@
         heightAnimator.start();
     }
 
+    /**
+     * Initialize the viewStates for the added children
+     *
+     * @param animationEvents the animation events who contain the added children
+     * @param finalState the final state to animate to
+     */
     private void initializeAddedViewStates(
-            ArrayList<NotificationStackScrollLayout.ChildHierarchyChangeEvent> mAnimationEvents,
+            ArrayList<NotificationStackScrollLayout.AnimationEvent> animationEvents,
             StackScrollState finalState) {
-        for (NotificationStackScrollLayout.ChildHierarchyChangeEvent event: mAnimationEvents) {
+        for (NotificationStackScrollLayout.AnimationEvent event: animationEvents) {
             View changingView = event.changingView;
-            if (event.animationType == NotificationStackScrollLayout.ChildHierarchyChangeEvent
+            if (event.animationType == NotificationStackScrollLayout.AnimationEvent
                     .ANIMATION_TYPE_ADD && !mHandledEvents.contains(event)) {
 
                 // This item is added, initialize it's properties.
                 StackScrollState.ViewState viewState = finalState.getViewStateForView(changingView);
+                if (viewState == null) {
+                    // The position for this child was never generated, let's continue.
+                    continue;
+                }
                 changingView.setAlpha(0);
                 changingView.setTranslationY(viewState.yTranslation);
                 changingView.setTranslationZ(viewState.zTranslation);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 0550dd4..50e2a2e 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3573,14 +3573,14 @@
         });
         swipeDismiss.setOnSwipeProgressChangedListener(
                 new SwipeDismissLayout.OnSwipeProgressChangedListener() {
+                    private static final float ALPHA_DECREASE = 0.5f;
                     private boolean mIsTranslucent = false;
-
                     @Override
                     public void onSwipeProgressChanged(
                             SwipeDismissLayout layout, float progress, float translate) {
                         WindowManager.LayoutParams newParams = getAttributes();
                         newParams.x = (int) translate;
-                        newParams.alpha = 1 - progress;
+                        newParams.alpha = 1 - (progress * ALPHA_DECREASE);
                         setAttributes(newParams);
 
                         int flags = 0;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 8bc669a..ae6aeee 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -667,7 +667,8 @@
     private void interceptPowerKeyDown(boolean handled) {
         mPowerKeyHandled = handled;
         if (!handled) {
-            mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
+            mHandler.postDelayed(mPowerLongPress,
+                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
         }
     }
 
@@ -706,9 +707,9 @@
         if (mKeyguardDelegate.isShowing()) {
             // Double the time it takes to take a screenshot from the keyguard
             return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
-                    ViewConfiguration.getGlobalActionKeyTimeout());
+                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
         }
-        return ViewConfiguration.getGlobalActionKeyTimeout();
+        return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
     }
 
     private void cancelPendingScreenshotChordAction() {
@@ -990,9 +991,9 @@
 
         // Match current screen state.
         if (mPowerManager.isInteractive()) {
-            screenTurningOn(null);
+            wakingUp(null);
         } else {
-            screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
+            goingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
         }
     }
 
@@ -4314,7 +4315,7 @@
     }
 
     @Override
-    public void screenTurnedOff(int why) {
+    public void goingToSleep(int why) {
         EventLog.writeEvent(70000, 0);
         synchronized (mLock) {
             mScreenOnEarly = false;
@@ -4330,7 +4331,7 @@
     }
 
     @Override
-    public void screenTurningOn(final ScreenOnListener screenOnListener) {
+    public void wakingUp(final ScreenOnListener screenOnListener) {
         EventLog.writeEvent(70000, 1);
         if (false) {
             RuntimeException here = new RuntimeException("here");
@@ -4776,7 +4777,11 @@
         mHandler.post(new Runnable() {
             @Override public void run() {
                 if (mBootMsgDialog == null) {
-                    mBootMsgDialog = new ProgressDialog(mContext) {
+                    int theme =  mContext.getPackageManager().hasSystemFeature(
+                            PackageManager.FEATURE_WATCH) ?
+                            com.android.internal.R.style.Theme_Micro_Dialog_Alert : 0;
+
+                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
                         // This dialog will consume all events coming in to
                         // it, to avoid it trying to do things too early in boot.
                         @Override public boolean dispatchKeyEvent(KeyEvent event) {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index 77d5076..2fa23c9 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -125,8 +125,10 @@
             // Register for the boot completed broadcast, so we can send the
             // ENABLE broacasts. If we try to send them now, they time out,
             // because the system isn't ready to handle them yet.
+            IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+            filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
             mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
-                    new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+                    filter, null, null);
 
             // Register for configuration changes so we can update the names
             // of the widgets when the locale changes.
@@ -135,7 +137,6 @@
 
             // Register for broadcasts about package install, etc., so we can
             // update the provider list.
-            IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_PACKAGE_ADDED);
             filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 0d6f548..e2a8ca2 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -212,6 +212,7 @@
         filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         registerForAirplaneMode(filter);
+        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiver(mReceiver, filter);
         loadStoredNameAndAddress();
         if (isBluetoothPersistedStateOn()) {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 6fc3e77..7ed1cc7 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1548,7 +1548,8 @@
 
                     mImeSwitcherNotification.setLatestEventInfo(
                             mContext, title, summary, mImeSwitchPendingIntent);
-                    if (mNotificationManager != null) {
+                    if ((mNotificationManager != null)
+                            && !mWindowManagerService.hasNavigationBar()) {
                         if (DEBUG) {
                             Slog.d(TAG, "--- show notification: label =  " + summary);
                         }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 62deec2..d6ecb46 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -426,29 +426,33 @@
             Slog.e(TAG,  "no geocoder provider found");
         }
 
-        // bind to fused provider
-        FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
-        FusedProxy fusedProxy = FusedProxy.createAndBind(
-                mContext,
-                mLocationHandler,
-                flpHardwareProvider.getLocationHardware(),
-                com.android.internal.R.bool.config_enableFusedLocationOverlay,
-                com.android.internal.R.string.config_fusedLocationProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames);
-        if(fusedProxy == null) {
-            Slog.e(TAG, "No FusedProvider found.");
-        }
+        // bind to fused provider if supported
+        if (FlpHardwareProvider.isSupported()) {
+          FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
+          FusedProxy fusedProxy = FusedProxy.createAndBind(
+                  mContext,
+                  mLocationHandler,
+                  flpHardwareProvider.getLocationHardware(),
+                  com.android.internal.R.bool.config_enableFusedLocationOverlay,
+                  com.android.internal.R.string.config_fusedLocationProviderPackageName,
+                  com.android.internal.R.array.config_locationProviderPackageNames);
+          if(fusedProxy == null) {
+              Slog.e(TAG, "Unable to bind FusedProxy.");
+          }
 
-        // bind to geofence provider
-        GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
-                com.android.internal.R.bool.config_enableGeofenceOverlay,
-                com.android.internal.R.string.config_geofenceProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames,
-                mLocationHandler,
-                gpsProvider.getGpsGeofenceProxy(),
-                flpHardwareProvider.getGeofenceHardware());
-        if (provider == null) {
-            Slog.e(TAG,  "no geofence provider found");
+          // bind to geofence provider
+          GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
+                  com.android.internal.R.bool.config_enableGeofenceOverlay,
+                  com.android.internal.R.string.config_geofenceProviderPackageName,
+                  com.android.internal.R.array.config_locationProviderPackageNames,
+                  mLocationHandler,
+                  gpsProvider.getGpsGeofenceProxy(),
+                  flpHardwareProvider.getGeofenceHardware());
+          if (provider == null) {
+              Slog.e(TAG,  "Unable to bind FLP Geofence proxy.");
+          }
+        } else {
+          Slog.e(TAG, "FLP HAL not supported.");
         }
 
         String[] testProviderStrings = resources.getStringArray(
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 8a30e50..4f0c9b5 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -20,19 +20,24 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
+import android.net.INetworkScoreCache;
 import android.net.INetworkScoreService;
-import android.net.NetworkKey;
 import android.net.NetworkScorerAppManager;
-import android.net.RssiCurve;
 import android.net.ScoredNetwork;
+import android.os.RemoteException;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.internal.R;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Backing service for {@link android.net.NetworkScoreManager}.
@@ -46,12 +51,11 @@
 
     private final Context mContext;
 
-    // TODO: Delete this temporary class once we have a real place for scores.
-    private final Map<NetworkKey, RssiCurve> mScoredNetworks;
+    private final Map<Integer, INetworkScoreCache> mScoreCaches;
 
     public NetworkScoreService(Context context) {
         mContext = context;
-        mScoredNetworks = new HashMap<>();
+        mScoreCaches = new HashMap<>();
     }
 
     /** Called when the system is ready to run third-party code but before it actually does so. */
@@ -76,10 +80,31 @@
                     " is not the active scorer.");
         }
 
-        // TODO: Propagate these scores down to the network subsystem layer instead of just holding
-        // them in memory.
+        // Separate networks by type.
+        Map<Integer, List<ScoredNetwork>> networksByType = new HashMap<>();
         for (ScoredNetwork network : networks) {
-            mScoredNetworks.put(network.networkKey, network.rssiCurve);
+            List<ScoredNetwork> networkList = networksByType.get(network.networkKey.type);
+            if (networkList == null) {
+                networkList = new ArrayList<>();
+                networksByType.put(network.networkKey.type, networkList);
+            }
+            networkList.add(network);
+        }
+
+        // Pass the scores of each type down to the appropriate network scorer.
+        for (Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) {
+            INetworkScoreCache scoreCache = mScoreCaches.get(entry.getKey());
+            if (scoreCache != null) {
+                try {
+                    scoreCache.updateScores(entry.getValue());
+                } catch (RemoteException e) {
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e);
+                    }
+                }
+            } else if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding");
+            }
         }
 
         return true;
@@ -112,8 +137,29 @@
 
     /** Clear scores. Callers are responsible for checking permissions as appropriate. */
     private void clearInternal() {
-        // TODO: Propagate the flush down to the network subsystem layer.
-        mScoredNetworks.clear();
+        Set<INetworkScoreCache> cachesToClear = getScoreCaches();
+
+        for (INetworkScoreCache scoreCache : cachesToClear) {
+            try {
+                scoreCache.clearScores();
+            } catch (RemoteException e) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "Unable to clear scores", e);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+        mContext.enforceCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS, TAG);
+        synchronized (mScoreCaches) {
+            if (mScoreCaches.containsKey(networkType)) {
+                throw new IllegalArgumentException(
+                        "Score cache already registered for type " + networkType);
+            }
+            mScoreCaches.put(networkType, scoreCache);
+        }
     }
 
     @Override
@@ -125,12 +171,28 @@
             return;
         }
         writer.println("Current scorer: " + currentScorer);
-        if (mScoredNetworks.isEmpty()) {
-            writer.println("No networks scored.");
-        } else {
-            for (Map.Entry<NetworkKey, RssiCurve> entry : mScoredNetworks.entrySet()) {
-                writer.println(entry.getKey() + ": " + entry.getValue());
+
+        for (INetworkScoreCache scoreCache : getScoreCaches()) {
+            try {
+                scoreCache.asBinder().dump(fd, args);
+            } catch (RemoteException e) {
+                writer.println("Unable to dump score cache");
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "Unable to dump score cache", e);
+                }
             }
         }
     }
+
+    /**
+     * Returns a set of all score caches that are currently active.
+     *
+     * <p>May be used to perform an action on all score caches without potentially strange behavior
+     * if a new scorer is registered during that action's execution.
+     */
+    private Set<INetworkScoreCache> getScoreCaches() {
+        synchronized (mScoreCaches) {
+            return new HashSet<>(mScoreCaches.values());
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/RecognitionManagerService.java b/services/core/java/com/android/server/RecognitionManagerService.java
index c2e749d..60d38ae 100644
--- a/services/core/java/com/android/server/RecognitionManagerService.java
+++ b/services/core/java/com/android/server/RecognitionManagerService.java
@@ -78,8 +78,10 @@
         mMonitor = new MyPackageMonitor();
         mMonitor.register(context, null, UserHandle.ALL, true);
         mIPm = AppGlobals.getPackageManager();
+        IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
-                new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+                filter, null, null);
     }
 
     public void systemReady() {
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index 415fcc1..50cfe48 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -97,13 +97,15 @@
 
         mObserver = new WiredAccessoryObserver();
 
+        IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         context.registerReceiver(new BroadcastReceiver() {
                     @Override
                     public void onReceive(Context ctx, Intent intent) {
                         bootCompleted();
                     }
                 },
-                new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+                filter, null, null);
     }
 
     private void bootCompleted() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0c91907..f908de2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -95,7 +95,6 @@
 import android.app.IProcessObserver;
 import android.app.IServiceConnection;
 import android.app.IStopUserCallback;
-import android.app.IThumbnailReceiver;
 import android.app.IUiAutomationConnection;
 import android.app.IUserSwitchObserver;
 import android.app.Instrumentation;
@@ -703,13 +702,6 @@
     String mBackupAppName = null;
     BackupRecord mBackupTarget = null;
 
-    /**
-     * List of PendingThumbnailsRecord objects of clients who are still
-     * waiting to receive all of the thumbnails for a task.
-     */
-    final ArrayList<PendingThumbnailsRecord> mPendingThumbnails =
-            new ArrayList<PendingThumbnailsRecord>();
-
     final ProviderMap mProviderMap;
 
     /**
@@ -1017,11 +1009,11 @@
 
     static class ProcessChangeItem {
         static final int CHANGE_ACTIVITIES = 1<<0;
-        static final int CHANGE_IMPORTANCE= 1<<1;
+        static final int CHANGE_PROCESS_STATE = 1<<1;
         int changes;
         int uid;
         int pid;
-        int importance;
+        int processState;
         boolean foregroundActivities;
     }
 
@@ -3200,11 +3192,10 @@
                             observer.onForegroundActivitiesChanged(item.pid, item.uid,
                                     item.foregroundActivities);
                         }
-                        if ((item.changes&ProcessChangeItem.CHANGE_IMPORTANCE) != 0) {
-                            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "IMPORTANCE CHANGED pid="
-                                    + item.pid + " uid=" + item.uid + ": " + item.importance);
-                            observer.onImportanceChanged(item.pid, item.uid,
-                                    item.importance);
+                        if ((item.changes&ProcessChangeItem.CHANGE_PROCESS_STATE) != 0) {
+                            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "PROCSTATE CHANGED pid="
+                                    + item.pid + " uid=" + item.uid + ": " + item.processState);
+                            observer.onProcessStateChanged(item.pid, item.uid, item.processState);
                         }
                     }
                 } catch (RemoteException e) {
@@ -5453,21 +5444,15 @@
             throw new IllegalArgumentException("File descriptors passed in Bundle");
         }
 
-        ActivityRecord r = null;
-
         final long origId = Binder.clearCallingIdentity();
 
         synchronized (this) {
-            r = ActivityRecord.isInStackLocked(token);
+            ActivityRecord r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
                 r.task.stack.activityStoppedLocked(r, icicle, thumbnail, description);
             }
         }
 
-        if (r != null) {
-            sendPendingThumbnail(r, null, null, null, false);
-        }
-
         trimApplications();
 
         Binder.restoreCallingIdentity(origId);
@@ -6983,66 +6968,24 @@
     // =========================================================
 
     @Override
-    public List<RunningTaskInfo> getTasks(int maxNum, int flags,
-                         IThumbnailReceiver receiver) {
+    public List<RunningTaskInfo> getTasks(int maxNum, int flags) {
+        final int callingUid = Binder.getCallingUid();
         ArrayList<RunningTaskInfo> list = new ArrayList<RunningTaskInfo>();
 
-        PendingThumbnailsRecord pending = new PendingThumbnailsRecord(receiver);
-        ActivityRecord topRecord = null;
-
         synchronized(this) {
             if (localLOGV) Slog.v(
-                TAG, "getTasks: max=" + maxNum + ", flags=" + flags
-                + ", receiver=" + receiver);
+                TAG, "getTasks: max=" + maxNum + ", flags=" + flags);
 
-            if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
-                    != PackageManager.PERMISSION_GRANTED) {
-                if (receiver != null) {
-                    // If the caller wants to wait for pending thumbnails,
-                    // it ain't gonna get them.
-                    try {
-                        receiver.finished();
-                    } catch (RemoteException ex) {
-                    }
-                }
-                String msg = "Permission Denial: getTasks() from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid()
-                        + " requires " + android.Manifest.permission.GET_TASKS;
-                Slog.w(TAG, msg);
-                throw new SecurityException(msg);
+            final boolean allowed = checkCallingPermission(
+                    android.Manifest.permission.GET_TASKS)
+                    == PackageManager.PERMISSION_GRANTED;
+            if (!allowed) {
+                Slog.w(TAG, "getTasks: caller " + callingUid
+                        + " does not hold GET_TASKS; limiting output");
             }
 
             // TODO: Improve with MRU list from all ActivityStacks.
-            topRecord = mStackSupervisor.getTasksLocked(maxNum, receiver, pending, list);
-
-            if (!pending.pendingRecords.isEmpty()) {
-                mPendingThumbnails.add(pending);
-            }
-        }
-
-        if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
-
-        if (topRecord != null) {
-            if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
-            try {
-                IApplicationThread topThumbnail = topRecord.app.thread;
-                topThumbnail.requestThumbnail(topRecord.appToken);
-            } catch (Exception e) {
-                Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
-                sendPendingThumbnail(null, topRecord.appToken, null, null, true);
-            }
-        }
-
-        if (pending.pendingRecords.isEmpty() && receiver != null) {
-            // In this case all thumbnails were available and the client
-            // is being asked to be told when the remaining ones come in...
-            // which is unusually, since the top-most currently running
-            // activity should never have a canned thumbnail!  Oh well.
-            try {
-                receiver.finished();
-            } catch (RemoteException ex) {
-            }
+            mStackSupervisor.getTasksLocked(maxNum, list, callingUid, allowed);
         }
 
         return list;
@@ -7055,12 +6998,18 @@
     @Override
     public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
             int flags, int userId) {
-        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
                 false, true, "getRecentTasks", null);
 
         synchronized (this) {
-            enforceCallingPermission(android.Manifest.permission.GET_TASKS,
-                    "getRecentTasks()");
+            final boolean allowed = checkCallingPermission(
+                    android.Manifest.permission.GET_TASKS)
+                    == PackageManager.PERMISSION_GRANTED;
+            if (!allowed) {
+                Slog.w(TAG, "getRecentTasks: caller " + callingUid
+                        + " does not hold GET_TASKS; limiting output");
+            }
             final boolean detailed = checkCallingPermission(
                     android.Manifest.permission.GET_DETAILED_TASKS)
                     == PackageManager.PERMISSION_GRANTED;
@@ -7095,6 +7044,13 @@
                         || (tr.intent == null)
                         || ((tr.intent.getFlags()
                                 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
+                    if (!allowed) {
+                        // If the caller doesn't have the GET_TASKS permission, then only
+                        // allow them to see a small subset of tasks -- their own and home.
+                        if (!tr.isHomeTask() && tr.creatorUid != callingUid) {
+                            continue;
+                        }
+                    }
                     ActivityManager.RecentTaskInfo rti
                             = new ActivityManager.RecentTaskInfo();
                     rti.id = tr.numActivities > 0 ? tr.taskId : -1;
@@ -7114,8 +7070,7 @@
                     final ArrayList<ActivityRecord> activities = tr.mActivities;
                     int activityNdx;
                     final int numActivities = activities.size();
-                    for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
-                            ++activityNdx) {
+                    for (activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
                         final ActivityRecord r = activities.get(activityNdx);
                         if (r.intent != null &&
                                 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
@@ -7123,14 +7078,34 @@
                             break;
                         }
                     }
-                    // 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;
+                    if (activityNdx > 0) {
+                        // Traverse downwards starting below break looking for set label, icon.
+                        // Note that if there are activities in the task but none of them set the
+                        // recent activity values, then we do not fall back to the last set
+                        // values in the TaskRecord.
+                        rti.activityValues = new ActivityManager.RecentsActivityValues();
+                        for (--activityNdx; activityNdx >= 0; --activityNdx) {
+                            final ActivityRecord r = activities.get(activityNdx);
+                            if (r.activityValues != null) {
+                                if (rti.activityValues.label == null) {
+                                    rti.activityValues.label = r.activityValues.label;
+                                    tr.lastActivityValues.label = r.activityValues.label;
+                                }
+                                if (rti.activityValues.icon == null) {
+                                    rti.activityValues.icon = r.activityValues.icon;
+                                    tr.lastActivityValues.icon = r.activityValues.icon;
+                                }
+                                if (rti.activityValues.colorPrimary == 0) {
+                                    rti.activityValues.colorPrimary = r.activityValues.colorPrimary;
+                                    tr.lastActivityValues.colorPrimary = r.activityValues.colorPrimary;
+                                }
+                            }
                         }
+                    } else {
+                        // If there are no activity records in this task, then we use the last
+                        // resolved values
+                        rti.activityValues =
+                                new ActivityManager.RecentsActivityValues(tr.lastActivityValues);
                     }
 
                     if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
@@ -7198,13 +7173,11 @@
     }
 
     @Override
-    public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
-            Bitmap activityIcon) {
+    public void setRecentsActivityValues(IBinder token, ActivityManager.RecentsActivityValues rav) {
         synchronized (this) {
             ActivityRecord r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
-                r.activityLabel = activityLabel.toString();
-                r.activityIcon = activityIcon;
+                r.activityValues = rav;
             }
         }
     }
@@ -7636,82 +7609,6 @@
     }
 
     // =========================================================
-    // THUMBNAILS
-    // =========================================================
-
-    public void reportThumbnail(IBinder token,
-            Bitmap thumbnail, CharSequence description) {
-        //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
-        final long origId = Binder.clearCallingIdentity();
-        sendPendingThumbnail(null, token, thumbnail, description, true);
-        Binder.restoreCallingIdentity(origId);
-    }
-
-    final void sendPendingThumbnail(ActivityRecord r, IBinder token,
-            Bitmap thumbnail, CharSequence description, boolean always) {
-        TaskRecord task;
-        ArrayList<PendingThumbnailsRecord> receivers = null;
-
-        //System.out.println("Send pending thumbnail: " + r);
-
-        synchronized(this) {
-            if (r == null) {
-                r = ActivityRecord.isInStackLocked(token);
-                if (r == null) {
-                    return;
-                }
-            }
-            if (thumbnail == null && r.thumbHolder != null) {
-                thumbnail = r.thumbHolder.lastThumbnail;
-                description = r.thumbHolder.lastDescription;
-            }
-            if (thumbnail == null && !always) {
-                // If there is no thumbnail, and this entry is not actually
-                // going away, then abort for now and pick up the next
-                // thumbnail we get.
-                return;
-            }
-            task = r.task;
-
-            int N = mPendingThumbnails.size();
-            int i=0;
-            while (i<N) {
-                PendingThumbnailsRecord pr = mPendingThumbnails.get(i);
-                //System.out.println("Looking in " + pr.pendingRecords);
-                if (pr.pendingRecords.remove(r)) {
-                    if (receivers == null) {
-                        receivers = new ArrayList<PendingThumbnailsRecord>();
-                    }
-                    receivers.add(pr);
-                    if (pr.pendingRecords.size() == 0) {
-                        pr.finished = true;
-                        mPendingThumbnails.remove(i);
-                        N--;
-                        continue;
-                    }
-                }
-                i++;
-            }
-        }
-
-        if (receivers != null) {
-            final int N = receivers.size();
-            for (int i=0; i<N; i++) {
-                try {
-                    PendingThumbnailsRecord pr = receivers.get(i);
-                    pr.receiver.newThumbnail(
-                        task != null ? task.taskId : -1, thumbnail, description);
-                    if (pr.finished) {
-                        pr.receiver.finished();
-                    }
-                } catch (Exception e) {
-                    Slog.w(TAG, "Exception thrown when sending thumbnail", e);
-                }
-            }
-        }
-    }
-
-    // =========================================================
     // CONTENT PROVIDERS
     // =========================================================
 
@@ -10635,6 +10532,7 @@
         int adj = app.curAdj;
         outInfo.importance = oomAdjToImportance(adj, outInfo);
         outInfo.importanceReasonCode = app.adjTypeCode;
+        outInfo.processState = app.curProcState;
     }
 
     public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
@@ -14690,7 +14588,7 @@
             app.keeping = true;
             app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
             app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
-            // System process can do UI, and when they do we want to have
+            // System processes can do UI, and when they do we want to have
             // them trim their memory after the user leaves the UI.  To
             // facilitate this, here we need to determine whether or not it
             // is currently showing UI.
@@ -15305,89 +15203,10 @@
         // it when computing the final cached adj later.  Note that we don't need to
         // worry about this for max adj above, since max adj will always be used to
         // keep it out of the cached vaues.
-        adj = app.modifyRawOomAdj(adj);
-
+        app.curAdj = app.modifyRawOomAdj(adj);
+        app.curSchedGroup = schedGroup;
         app.curProcState = procState;
-
-        int importance = app.memImportance;
-        if (importance == 0 || adj != app.curAdj || schedGroup != app.curSchedGroup) {
-            app.curAdj = adj;
-            app.curSchedGroup = schedGroup;
-            if (!interesting) {
-                // For this reporting, if there is not something explicitly
-                // interesting in this process then we will push it to the
-                // background importance.
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-            } else if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-            } else if (adj >= ProcessList.SERVICE_B_ADJ) {
-                importance =  ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
-            } else if (adj >= ProcessList.HOME_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-            } else if (adj >= ProcessList.SERVICE_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
-            } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
-            } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
-            } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
-            } else if (adj >= ProcessList.FOREGROUND_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
-            } else {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERSISTENT;
-            }
-        }
-
-        int changes = importance != app.memImportance ? ProcessChangeItem.CHANGE_IMPORTANCE : 0;
-        if (foregroundActivities != app.foregroundActivities) {
-            changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
-        }
-        if (changes != 0) {
-            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Changes in " + app + ": " + changes);
-            app.memImportance = importance;
-            app.foregroundActivities = foregroundActivities;
-            int i = mPendingProcessChanges.size()-1;
-            ProcessChangeItem item = null;
-            while (i >= 0) {
-                item = mPendingProcessChanges.get(i);
-                if (item.pid == app.pid) {
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Re-using existing item: " + item);
-                    break;
-                }
-                i--;
-            }
-            if (i < 0) {
-                // No existing item in pending changes; need a new one.
-                final int NA = mAvailProcessChanges.size();
-                if (NA > 0) {
-                    item = mAvailProcessChanges.remove(NA-1);
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Retreiving available item: " + item);
-                } else {
-                    item = new ProcessChangeItem();
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Allocating new item: " + item);
-                }
-                item.changes = 0;
-                item.pid = app.pid;
-                item.uid = app.info.uid;
-                if (mPendingProcessChanges.size() == 0) {
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG,
-                            "*** Enqueueing dispatch processes changed!");
-                    mHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED).sendToTarget();
-                }
-                mPendingProcessChanges.add(item);
-            }
-            item.changes |= changes;
-            item.importance = importance;
-            item.foregroundActivities = foregroundActivities;
-            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Item "
-                    + Integer.toHexString(System.identityHashCode(item))
-                    + " " + app.toShortString() + ": changes=" + item.changes
-                    + " importance=" + item.importance
-                    + " foreground=" + item.foregroundActivities
-                    + " type=" + app.adjType + " source=" + app.adjSource
-                    + " target=" + app.adjTarget);
-        }
+        app.foregroundActivities = foregroundActivities;
 
         return app.curRawAdj;
     }
@@ -15660,7 +15479,7 @@
     }
 
     private final boolean applyOomAdjLocked(ProcessRecord app, boolean wasKeeping,
-            ProcessRecord TOP_APP, boolean doingAll, boolean reportingProcessState, long now) {
+            ProcessRecord TOP_APP, boolean doingAll, long now) {
         boolean success = true;
 
         if (app.curRawAdj != app.setRawAdj) {
@@ -15679,6 +15498,8 @@
             app.setRawAdj = app.curRawAdj;
         }
 
+        int changes = 0;
+
         if (app.curAdj != app.setAdj) {
             ProcessList.setOomAdj(app.pid, app.curAdj);
             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
@@ -15720,9 +15541,14 @@
                         app.curSchedGroup <= Process.THREAD_GROUP_BG_NONINTERACTIVE);
             }
         }
+        if (app.repForegroundActivities != app.foregroundActivities) {
+            app.repForegroundActivities = app.foregroundActivities;
+            changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
+        }
         if (app.repProcState != app.curProcState) {
             app.repProcState = app.curProcState;
-            if (!reportingProcessState && app.thread != null) {
+            changes |= ProcessChangeItem.CHANGE_PROCESS_STATE;
+            if (app.thread != null) {
                 try {
                     if (false) {
                         //RuntimeException h = new RuntimeException("here");
@@ -15767,6 +15593,51 @@
                 app.procStateChanged = true;
             }
         }
+
+        if (changes != 0) {
+            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Changes in " + app + ": " + changes);
+            int i = mPendingProcessChanges.size()-1;
+            ProcessChangeItem item = null;
+            while (i >= 0) {
+                item = mPendingProcessChanges.get(i);
+                if (item.pid == app.pid) {
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Re-using existing item: " + item);
+                    break;
+                }
+                i--;
+            }
+            if (i < 0) {
+                // No existing item in pending changes; need a new one.
+                final int NA = mAvailProcessChanges.size();
+                if (NA > 0) {
+                    item = mAvailProcessChanges.remove(NA-1);
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Retreiving available item: " + item);
+                } else {
+                    item = new ProcessChangeItem();
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Allocating new item: " + item);
+                }
+                item.changes = 0;
+                item.pid = app.pid;
+                item.uid = app.info.uid;
+                if (mPendingProcessChanges.size() == 0) {
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG,
+                            "*** Enqueueing dispatch processes changed!");
+                    mHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED).sendToTarget();
+                }
+                mPendingProcessChanges.add(item);
+            }
+            item.changes |= changes;
+            item.processState = app.repProcState;
+            item.foregroundActivities = app.repForegroundActivities;
+            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Item "
+                    + Integer.toHexString(System.identityHashCode(item))
+                    + " " + app.toShortString() + ": changes=" + item.changes
+                    + " procState=" + item.processState
+                    + " foreground=" + item.foregroundActivities
+                    + " type=" + app.adjType + " source=" + app.adjSource
+                    + " target=" + app.adjTarget);
+        }
+
         return success;
     }
 
@@ -15777,7 +15648,7 @@
     }
 
     private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
-            ProcessRecord TOP_APP, boolean doingAll, boolean reportingProcessState, long now) {
+            ProcessRecord TOP_APP, boolean doingAll, long now) {
         if (app.thread == null) {
             return false;
         }
@@ -15786,8 +15657,7 @@
 
         computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);
 
-        return applyOomAdjLocked(app, wasKeeping, TOP_APP, doingAll,
-                reportingProcessState, now);
+        return applyOomAdjLocked(app, wasKeeping, TOP_APP, doingAll, now);
     }
 
     final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
@@ -15853,10 +15723,6 @@
     }
 
     final boolean updateOomAdjLocked(ProcessRecord app) {
-        return updateOomAdjLocked(app, false);
-    }
-
-    final boolean updateOomAdjLocked(ProcessRecord app, boolean doingProcessState) {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
         final boolean wasCached = app.cached;
@@ -15869,7 +15735,7 @@
         // need to do a complete oom adj.
         final int cachedAdj = app.curRawAdj >= ProcessList.CACHED_APP_MIN_ADJ
                 ? app.curRawAdj : ProcessList.UNKNOWN_ADJ;
-        boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false, doingProcessState,
+        boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false,
                 SystemClock.uptimeMillis());
         if (wasCached != app.cached || app.curRawAdj == ProcessList.UNKNOWN_ADJ) {
             // Changed to/from cached state, so apps after it in the LRU
@@ -16002,7 +15868,7 @@
                     }
                 }
 
-                applyOomAdjLocked(app, wasKeeping, TOP_APP, true, false, now);
+                applyOomAdjLocked(app, wasKeeping, TOP_APP, true, now);
 
                 // Count the number of process types.
                 switch (app.curProcState) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 7a44473..7c3f288 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -23,6 +23,7 @@
 import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
 
+import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ResultInfo;
 import android.content.ComponentName;
@@ -131,7 +132,6 @@
     boolean sleeping;       // have we told the activity to sleep?
     boolean waitingVisible; // true if waiting for a new act to become vis
     boolean nowVisible;     // is this activity's window visible?
-    boolean thumbnailNeeded;// has someone requested a thumbnail?
     boolean idle;           // has the activity gone idle?
     boolean hasBeenLaunched;// has this activity ever been launched?
     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
@@ -148,8 +148,7 @@
     boolean mStartingWindowShown = false;
     ActivityContainer mInitialActivityContainer;
 
-    String activityLabel;
-    Bitmap activityIcon;
+    ActivityManager.RecentsActivityValues activityValues; // the recents information for this activity
 
     void dump(PrintWriter pw, String prefix) {
         final long now = SystemClock.uptimeMillis();
@@ -239,7 +238,6 @@
                 pw.print(" immersive="); pw.print(immersive);
                 pw.print(" launchMode="); pw.println(launchMode);
         pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
-                pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
         pw.print(prefix); pw.print("mActivityType=");
                 pw.println(activityTypeToString(mActivityType));
@@ -375,7 +373,6 @@
         visible = true;
         waitingVisible = false;
         nowVisible = false;
-        thumbnailNeeded = false;
         idle = false;
         hasBeenLaunched = false;
         mStackSupervisor = supervisor;
@@ -483,7 +480,7 @@
     void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
         if (task != null && task.removeActivity(this)) {
             if (task != newTask) {
-                task.stack.removeTask(task);
+                task.stack.removeTask(task, false);
             } else {
                 Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
                         (newTask == null ? null : newTask.stack));
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 6769c9c..ee39b67 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -53,7 +53,6 @@
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
 import android.app.IActivityController;
-import android.app.IThumbnailReceiver;
 import android.app.ResultInfo;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.ComponentName;
@@ -73,7 +72,6 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.util.EventLog;
@@ -1098,6 +1096,36 @@
                 ensureActivitiesVisibleLocked(r, starting, null, configChanges, forceHomeShown);
     }
 
+    // Checks if any of the stacks above this one has a fullscreen activity behind it.
+    // If so, this stack is hidden, otherwise it is visible.
+    private boolean isStackVisible() {
+        if (!isAttached()) {
+            return false;
+        }
+
+        if (mStackSupervisor.isFrontStack(this)) {
+            return true;
+        }
+
+        // Start at the task above this one and go up, looking for a visible
+        // fullscreen activity, or a translucent activity that requested the
+        // wallpaper to be shown behind it.
+        for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
+            final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
+            for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
+                final ArrayList<ActivityRecord> activities = tasks.get(taskNdx).mActivities;
+                for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
+                    final ActivityRecord r = activities.get(activityNdx);
+                    if (!r.finishing && r.visible && r.fullscreen) {
+                        return false;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
     /**
      * Make sure that all activities that need to be visible (that is, they
      * currently can be seen by the user) actually are.
@@ -1122,8 +1150,8 @@
         // make sure any activities under it are now visible.
         boolean aboveTop = true;
         boolean showHomeBehindStack = false;
-        boolean behindFullscreen = !mStackSupervisor.isFrontStack(this) &&
-                !(forceHomeShown && isHomeStack());
+        boolean behindFullscreen = !isStackVisible();
+
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
             final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -2537,13 +2565,6 @@
 
         finishActivityResultsLocked(r, resultCode, resultData);
 
-        if (!mService.mPendingThumbnails.isEmpty()) {
-            // There are clients waiting to receive thumbnails so, in case
-            // this is an activity that someone is waiting for, add it
-            // to the pending list so we can correctly update the clients.
-            mStackSupervisor.mCancelledThumbnails.add(r);
-        }
-
         if (mResumedActivity == r) {
             boolean endTask = index <= 0;
             if (DEBUG_VISBILITY || DEBUG_TRANSITION) Slog.v(TAG,
@@ -2782,13 +2803,6 @@
             cleanUpActivityServicesLocked(r);
         }
 
-        if (!mService.mPendingThumbnails.isEmpty()) {
-            // There are clients waiting to receive thumbnails so, in case
-            // this is an activity that someone is waiting for, add it
-            // to the pending list so we can correctly update the clients.
-            mStackSupervisor.mCancelledThumbnails.add(r);
-        }
-
         // Get rid of any pending idle timeouts.
         removeTimeoutsForActivityLocked(r);
     }
@@ -2827,7 +2841,7 @@
             if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
                 mStackSupervisor.moveHomeToTop();
             }
-            removeTask(task);
+            removeTask(task, false);
         }
         cleanUpActivityServicesLocked(r);
         r.removeUriPermissionsLocked();
@@ -3535,9 +3549,7 @@
         return didSomething;
     }
 
-    ActivityRecord getTasksLocked(IThumbnailReceiver receiver,
-            PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
-        ActivityRecord topRecord = null;
+    void getTasksLocked(List<RunningTaskInfo> list, int callingUid, boolean allowed) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
             ActivityRecord r = null;
@@ -3548,6 +3560,9 @@
             if (activities.isEmpty()) {
                 continue;
             }
+            if (!allowed && !task.isHomeTask() && task.creatorUid != callingUid) {
+                continue;
+            }
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                 r = activities.get(activityNdx);
 
@@ -3581,23 +3596,8 @@
             ci.numRunning = numRunning;
             //System.out.println(
             //    "#" + maxNum + ": " + " descr=" + ci.description);
-            if (receiver != null) {
-                if (localLOGV) Slog.v(
-                    TAG, "State=" + top.state + "Idle=" + top.idle
-                    + " app=" + top.app
-                    + " thr=" + (top.app != null ? top.app.thread : null));
-                if (top.state == ActivityState.RESUMED || top.state == ActivityState.PAUSING) {
-                    if (top.idle && top.app != null && top.app.thread != null) {
-                        topRecord = top;
-                    } else {
-                        top.thumbnailNeeded = true;
-                    }
-                }
-                pending.pendingRecords.add(top);
-            }
             list.add(ci);
         }
-        return topRecord;
     }
 
     public void unhandledBackLocked() {
@@ -3717,7 +3717,7 @@
         return starting;
     }
 
-    void removeTask(TaskRecord task) {
+    void removeTask(TaskRecord task, boolean moving) {
         mStackSupervisor.endLockTaskModeIfTaskEnding(task);
         mWindowManager.removeTask(task.taskId);
         final ActivityRecord r = mResumedActivity;
@@ -3731,9 +3731,13 @@
             mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
         }
         mTaskHistory.remove(task);
-        if (task.voiceInteractor != null) {
+        if (!moving && task.voiceSession != null) {
             // This task was a voice interaction, so it should not remain on the
             // recent tasks list.
+            try {
+                task.voiceSession.taskFinished(task.intent, task.taskId);
+            } catch (RemoteException e) {
+            }
             mService.mRecentTasks.remove(task);
         }
 
@@ -3753,7 +3757,7 @@
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
             boolean toTop) {
         TaskRecord task = new TaskRecord(taskId, info, intent, voiceSession, voiceInteractor);
-        addTask(task, toTop);
+        addTask(task, toTop, false);
         return task;
     }
 
@@ -3761,13 +3765,19 @@
         return new ArrayList<TaskRecord>(mTaskHistory);
     }
 
-    void addTask(final TaskRecord task, final boolean toTop) {
+    void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
         task.stack = this;
         if (toTop) {
             insertTaskAtTop(task);
         } else {
             mTaskHistory.add(0, task);
         }
+        if (!moving && task.voiceSession != null) {
+            try {
+                task.voiceSession.taskStarted(task.intent, task.taskId);
+            } catch (RemoteException e) {
+            }
+        }
     }
 
     public int getStackId() {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 3770a07..8829b5f 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -41,7 +41,6 @@
 import android.app.IActivityContainerCallback;
 import android.app.IActivityManager;
 import android.app.IApplicationThread;
-import android.app.IThumbnailReceiver;
 import android.app.PendingIntent;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.IActivityManager.WaitResult;
@@ -191,10 +190,6 @@
     /** List of activities that are in the process of going to sleep. */
     final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
 
-    /** List of ActivityRecord objects that have been finished and must still report back to a
-     * pending thumbnail receiver. */
-    final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
-
     /** Used on user changes */
     final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
 
@@ -591,10 +586,7 @@
         return null;
     }
 
-    ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
-            PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
-        ActivityRecord r = null;
-
+    void getTasksLocked(int maxNum, List<RunningTaskInfo> list, int callingUid, boolean allowed) {
         // Gather all of the running tasks for each stack into runningTaskLists.
         ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists =
                 new ArrayList<ArrayList<RunningTaskInfo>>();
@@ -605,10 +597,7 @@
                 final ActivityStack stack = stacks.get(stackNdx);
                 ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
                 runningTaskLists.add(stackTaskList);
-                final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList);
-                if (r == null && isFrontStack(stack)) {
-                    r = ar;
-                }
+                stack.getTasksLocked(stackTaskList, callingUid, allowed);
             }
         }
 
@@ -635,8 +624,6 @@
                 break;
             }
         }
-
-        return r;
     }
 
     ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
@@ -1912,7 +1899,6 @@
         ArrayList<UserStartedState> startingUsers = null;
         int NS = 0;
         int NF = 0;
-        IApplicationThread sendThumbnail = null;
         boolean booting = false;
         boolean enableScreen = false;
         boolean activityRemoved = false;
@@ -1940,11 +1926,6 @@
             // us, we can now deliver.
             r.idle = true;
 
-            if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
-                sendThumbnail = r.app.thread;
-                r.thumbnailNeeded = false;
-            }
-
             //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
             if (!mService.mBooted && isFrontStack(r.task.stack)) {
                 mService.mBooted = true;
@@ -1976,15 +1957,6 @@
             mFinishingActivities.clear();
         }
 
-        final ArrayList<ActivityRecord> thumbnails;
-        final int NT = mCancelledThumbnails.size();
-        if (NT > 0) {
-            thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
-            mCancelledThumbnails.clear();
-        } else {
-            thumbnails = null;
-        }
-
         if (isFrontStack(mHomeStack)) {
             booting = mService.mBooting;
             mService.mBooting = false;
@@ -1995,28 +1967,6 @@
             mStartingUsers.clear();
         }
 
-        // Perform the following actions from unsynchronized state.
-        final IApplicationThread thumbnailThread = sendThumbnail;
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                if (thumbnailThread != null) {
-                    try {
-                        thumbnailThread.requestThumbnail(token);
-                    } catch (Exception e) {
-                        Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
-                        mService.sendPendingThumbnail(null, token, null, null, true);
-                    }
-                }
-
-                // Report back to any thumbnail receivers.
-                for (int i = 0; i < NT; i++) {
-                    ActivityRecord r = thumbnails.get(i);
-                    mService.sendPendingThumbnail(r, null, null, null, true);
-                }
-            }
-        });
-
         // Stop any activities that are scheduled to do so but have been
         // waiting for the next one to start.
         for (int i = 0; i < NS; i++) {
@@ -2287,8 +2237,8 @@
             Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
             return;
         }
-        task.stack.removeTask(task);
-        stack.addTask(task, toTop);
+        task.stack.removeTask(task, true);
+        stack.addTask(task, toTop, true);
         mWindowManager.addTask(taskId, stackId, toTop);
         resumeTopActivitiesLocked();
     }
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index b15fa5d..9d6481a 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -503,7 +503,7 @@
                     // are already core system stuff so don't matter for this.
                     r.curApp = filter.receiverList.app;
                     filter.receiverList.app.curReceiver = r;
-                    mService.updateOomAdjLocked(r.curApp, true);
+                    mService.updateOomAdjLocked(r.curApp);
                 }
             }
             try {
diff --git a/services/core/java/com/android/server/am/PendingThumbnailsRecord.java b/services/core/java/com/android/server/am/PendingThumbnailsRecord.java
deleted file mode 100644
index e4eb4d0..0000000
--- a/services/core/java/com/android/server/am/PendingThumbnailsRecord.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2006 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.am;
-
-import android.app.IThumbnailReceiver;
-
-import java.util.HashSet;
-
-/**
- * This class keeps track of calls to getTasks() that are still
- * waiting for thumbnail images.
- */
-final class PendingThumbnailsRecord
-{
-    final IThumbnailReceiver receiver;   // who is waiting.
-    final HashSet<ActivityRecord> pendingRecords; // HistoryRecord objects we still wait for.
-    boolean finished;       // Is pendingRecords empty?
-
-    PendingThumbnailsRecord(IThumbnailReceiver _receiver)
-    {
-        receiver = _receiver;
-        pendingRecords = new HashSet<ActivityRecord>();
-        finished = false;
-    }
-}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index d04a6b2..8d7d300 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -77,7 +77,6 @@
     int curSchedGroup;          // Currently desired scheduling class
     int setSchedGroup;          // Last set to background scheduling class
     int trimMemoryLevel;        // Last selected memory trimming level
-    int memImportance;          // Importance constant computed from curAdj
     int curProcState = -1;      // Currently computed process state: ActivityManager.PROCESS_STATE_*
     int repProcState = -1;      // Last reported process state
     int setProcState = -1;      // Last set process state in process tracker
@@ -91,6 +90,7 @@
     boolean hasStartedServices; // Are there any started services running in this process?
     boolean foregroundServices; // Running any services that are foreground?
     boolean foregroundActivities; // Running any activities that are foreground?
+    boolean repForegroundActivities; // Last reported foreground activities.
     boolean systemNoUi;         // This is a system process, but not currently showing UI.
     boolean hasShownUi;         // Has UI been shown in this process since it was started?
     boolean pendingUiClean;     // Want to clean up resources from showing UI?
@@ -267,9 +267,10 @@
             pw.print(prefix); pw.print("persistent="); pw.print(persistent);
                     pw.print(" removed="); pw.println(removed);
         }
-        if (hasClientActivities || foregroundActivities) {
+        if (hasClientActivities || foregroundActivities || repForegroundActivities) {
             pw.print(prefix); pw.print("hasClientActivities="); pw.print(hasClientActivities);
-                    pw.print(" foregroundActivities="); pw.println(foregroundActivities);
+                    pw.print(" foregroundActivities="); pw.print(foregroundActivities);
+                    pw.print(" (rep="); pw.print(repForegroundActivities); pw.println(")");
         }
         if (hasStartedServices) {
             pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 68da54d..9f0bc10 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -52,9 +52,15 @@
 
     String stringName;      // caching of toString() result.
     int userId;             // user for which this task was created
+    int creatorUid;         // The app uid that originally created the task
 
     int numFullscreen;      // Number of fullscreen activities.
 
+    // This represents the last resolved activity values for this task
+    // NOTE: This value needs to be persisted with each task
+    ActivityManager.RecentsActivityValues lastActivityValues =
+            new ActivityManager.RecentsActivityValues();
+
     /** List of all activities in the task arranged in history order */
     final ArrayList<ActivityRecord> mActivities = new ArrayList<ActivityRecord>();
 
@@ -131,9 +137,8 @@
             rootWasReset = true;
         }
 
-        if (info.applicationInfo != null) {
-            userId = UserHandle.getUserId(info.applicationInfo.uid);
-        }
+        userId = UserHandle.getUserId(info.applicationInfo.uid);
+        creatorUid = info.applicationInfo.uid;
     }
 
     void disposeThumbnail() {
diff --git a/services/core/java/com/android/server/am/UsageStatsService.java b/services/core/java/com/android/server/am/UsageStatsService.java
index 587f949..42cf900 100644
--- a/services/core/java/com/android/server/am/UsageStatsService.java
+++ b/services/core/java/com/android/server/am/UsageStatsService.java
@@ -73,42 +73,44 @@
     private static final boolean localLOGV = false;
     private static final boolean REPORT_UNEXPECTED = false;
     private static final String TAG = "UsageStats";
-    
+
     // Current on-disk Parcel version
     private static final int VERSION = 1008;
 
     private static final int CHECKIN_VERSION = 4;
-    
+
     private static final String FILE_PREFIX = "usage-";
 
     private static final String FILE_HISTORY = FILE_PREFIX + "history.xml";
 
-    private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms
-    
+    private static final int FILE_WRITE_INTERVAL = (localLOGV) ? 0 : 30*60*1000; // 30m in ms
+
     private static final int MAX_NUM_FILES = 5;
-    
+
     private static final int NUM_LAUNCH_TIME_BINS = 10;
     private static final int[] LAUNCH_TIME_BINS = {
         250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000
     };
-    
+
     static IUsageStats sService;
     private Context mContext;
     // structure used to maintain statistics since the last checkin.
-    final private ArrayMap<String, PkgUsageStatsExtended> mStats;
+    final private ArrayMap<String, PkgUsageStatsExtended> mStats
+            = new ArrayMap<String, PkgUsageStatsExtended>();
 
     // Maintains the last time any component was resumed, for all time.
-    final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes;
+    final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes
+            = new ArrayMap<String, ArrayMap<String, Long>>();
 
     // To remove last-resume time stats when a pacakge is removed.
     private PackageMonitor mPackageMonitor;
 
     // Lock to update package stats. Methods suffixed by SLOCK should invoked with
     // this lock held
-    final Object mStatsLock;
+    final Object mStatsLock = new Object();
     // Lock to write to file. Methods suffixed by FLOCK should invoked with
     // this lock held.
-    final Object mFileLock;
+    final Object mFileLock = new Object();
     // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
     private String mLastResumedPkg;
     private String mLastResumedComp;
@@ -118,52 +120,53 @@
     private String mFileLeaf;
     private File mDir;
 
-    private Calendar mCal; // guarded by itself
+    private final Calendar mCal // guarded by itself
+            = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
 
     private final AtomicInteger mLastWriteDay = new AtomicInteger(-1);
     private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0);
     private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false);
-    
+
     static class TimeStats {
-        int count;
-        int[] times = new int[NUM_LAUNCH_TIME_BINS];
-        
+        int mCount;
+        final int[] mTimes = new int[NUM_LAUNCH_TIME_BINS];
+
         TimeStats() {
         }
-        
+
         void incCount() {
-            count++;
+            mCount++;
         }
-        
+
         void add(int val) {
             final int[] bins = LAUNCH_TIME_BINS;
             for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
                 if (val < bins[i]) {
-                    times[i]++;
+                    mTimes[i]++;
                     return;
                 }
             }
-            times[NUM_LAUNCH_TIME_BINS-1]++;
+            mTimes[NUM_LAUNCH_TIME_BINS-1]++;
         }
-        
+
         TimeStats(Parcel in) {
-            count = in.readInt();
-            final int[] localTimes = times;
+            mCount = in.readInt();
+            final int[] localTimes = mTimes;
             for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                 localTimes[i] = in.readInt();
             }
         }
-        
+
         void writeToParcel(Parcel out) {
-            out.writeInt(count);
-            final int[] localTimes = times;
+            out.writeInt(mCount);
+            final int[] localTimes = mTimes;
             for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                 out.writeInt(localTimes[i]);
             }
         }
     }
-    
-    private class PkgUsageStatsExtended {
+
+    static class PkgUsageStatsExtended {
         final ArrayMap<String, TimeStats> mLaunchTimes
                 = new ArrayMap<String, TimeStats>();
         final ArrayMap<String, TimeStats> mFullyDrawnTimes
@@ -172,18 +175,18 @@
         long mUsageTime;
         long mPausedTime;
         long mResumedTime;
-        
+
         PkgUsageStatsExtended() {
             mLaunchCount = 0;
             mUsageTime = 0;
         }
-        
+
         PkgUsageStatsExtended(Parcel in) {
             mLaunchCount = in.readInt();
             mUsageTime = in.readLong();
             if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount
                     + ", Usage time:" + mUsageTime);
-            
+
             final int numLaunchTimeStats = in.readInt();
             if (localLOGV) Slog.v(TAG, "Reading launch times: " + numLaunchTimeStats);
             mLaunchTimes.ensureCapacity(numLaunchTimeStats);
@@ -207,16 +210,16 @@
 
         void updateResume(String comp, boolean launched) {
             if (launched) {
-                mLaunchCount ++;
+                mLaunchCount++;
             }
             mResumedTime = SystemClock.elapsedRealtime();
         }
-        
+
         void updatePause() {
             mPausedTime =  SystemClock.elapsedRealtime();
             mUsageTime += (mPausedTime - mResumedTime);
         }
-        
+
         void addLaunchCount(String comp) {
             TimeStats times = mLaunchTimes.get(comp);
             if (times == null) {
@@ -225,7 +228,7 @@
             }
             times.incCount();
         }
-        
+
         void addLaunchTime(String comp, int millis) {
             TimeStats times = mLaunchTimes.get(comp);
             if (times == null) {
@@ -260,7 +263,7 @@
                 mFullyDrawnTimes.valueAt(i).writeToParcel(out);
             }
         }
-        
+
         void clear() {
             mLaunchTimes.clear();
             mFullyDrawnTimes.clear();
@@ -268,32 +271,25 @@
             mUsageTime = 0;
         }
     }
-    
+
     UsageStatsService(String dir) {
-        mStats = new ArrayMap<String, PkgUsageStatsExtended>();
-        mLastResumeTimes = new ArrayMap<String, ArrayMap<String, Long>>();
-        mStatsLock = new Object();
-        mFileLock = new Object();
+        if (localLOGV) Slog.v(TAG, "UsageStatsService: " + dir);
         mDir = new File(dir);
-        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
-        
         mDir.mkdir();
-        
-        // Remove any old usage files from previous versions.
+
+        // Remove any old /data/system/usagestats.* files from previous versions.
         File parentDir = mDir.getParentFile();
-        String fList[] = parentDir.list();
-        if (fList != null) {
+        String files[] = parentDir.list();
+        if (files != null) {
             String prefix = mDir.getName() + ".";
-            int i = fList.length;
-            while (i > 0) {
-                i--;
-                if (fList[i].startsWith(prefix)) {
-                    Slog.i(TAG, "Deleting old usage file: " + fList[i]);
-                    (new File(parentDir, fList[i])).delete();
+            for (String file : files) {
+                if (file.startsWith(prefix)) {
+                    Slog.i(TAG, "Deleting old usage file: " + file);
+                    (new File(parentDir, file)).delete();
                 }
             }
         }
-        
+
         // Update current stats which are binned by date
         mFileLeaf = getCurrentDateStr(FILE_PREFIX);
         mFile = new File(mDir, mFileLeaf);
@@ -310,11 +306,11 @@
      */
     private String getCurrentDateStr(String prefix) {
         StringBuilder sb = new StringBuilder();
+        if (prefix != null) {
+            sb.append(prefix);
+        }
         synchronized (mCal) {
             mCal.setTimeInMillis(System.currentTimeMillis());
-            if (prefix != null) {
-                sb.append(prefix);
-            }
             sb.append(mCal.get(Calendar.YEAR));
             int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
             if (mm < 10) {
@@ -329,17 +325,20 @@
         }
         return sb.toString();
     }
-    
+
     private Parcel getParcelForFile(File file) throws IOException {
         FileInputStream stream = new FileInputStream(file);
-        byte[] raw = readFully(stream);
-        Parcel in = Parcel.obtain();
-        in.unmarshall(raw, 0, raw.length);
-        in.setDataPosition(0);
-        stream.close();
-        return in;
+        try {
+            byte[] raw = readFully(stream);
+            Parcel in = Parcel.obtain();
+            in.unmarshall(raw, 0, raw.length);
+            in.setDataPosition(0);
+            return in;
+        } finally {
+            stream.close();
+        }
     }
-    
+
     private void readStatsFromFile() {
         File newFile = mFile;
         synchronized (mFileLock) {
@@ -356,12 +355,13 @@
             }
         }
     }
-    
+
     private void readStatsFLOCK(File file) throws IOException {
         Parcel in = getParcelForFile(file);
         int vers = in.readInt();
-        if (vers != VERSION) {
-            Slog.w(TAG, "Usage stats version changed; dropping");
+        if (vers != VERSION) {  // vers will be 0 if the parcel file was empty
+            Slog.w(TAG, "Usage stats version of " + file + " changed from " + vers + " to "
+                   + VERSION + "; dropping");
             return;
         }
         int N = in.readInt();
@@ -382,12 +382,12 @@
     private void readHistoryStatsFromFile() {
         synchronized (mFileLock) {
             if (mHistoryFile.getBaseFile().exists()) {
-                readHistoryStatsFLOCK(mHistoryFile);
+                readHistoryStatsFLOCK();
             }
         }
     }
 
-    private void readHistoryStatsFLOCK(AtomicFile file) {
+    private void readHistoryStatsFLOCK() {
         FileInputStream fis = null;
         try {
             fis = mHistoryFile.openRead();
@@ -470,12 +470,12 @@
         }
         return fileList;
     }
-    
+
     private void checkFileLimitFLOCK() {
         // Get all usage stats output files
         ArrayList<String> fileList = getUsageStatsFileListFLOCK();
         if (fileList == null) {
-            // Strange but we dont have to delete any thing
+            // Empty /data/system/usagestats/ so we don't have anything to delete
             return;
         }
         int count = fileList.size();
@@ -575,8 +575,8 @@
                 }
 
                 if (dayChanged || forceWriteHistoryStats) {
-                    // Write history stats daily, or when forced (due to shutdown).
-                    writeHistoryStatsFLOCK(mHistoryFile);
+                    // Write history stats daily or when forced (due to shutdown) or when debugging.
+                    writeHistoryStatsFLOCK();
                 }
 
                 // Delete the backup file
@@ -638,10 +638,10 @@
         }
     }
 
-    private void writeHistoryStatsFLOCK(AtomicFile historyFile) {
+    private void writeHistoryStatsFLOCK() {
         FileOutputStream fos = null;
         try {
-            fos = historyFile.startWrite();
+            fos = mHistoryFile.startWrite();
             XmlSerializer out = new FastXmlSerializer();
             out.setOutput(fos, "utf-8");
             out.startDocument(null, true);
@@ -664,11 +664,11 @@
             out.endTag(null, "usage-history");
             out.endDocument();
 
-            historyFile.finishWrite(fos);
+            mHistoryFile.finishWrite(fos);
         } catch (IOException e) {
             Slog.w(TAG,"Error writing history stats" + e);
             if (fos != null) {
-                historyFile.failWrite(fos);
+                mHistoryFile.failWrite(fos);
             }
         }
     }
@@ -711,7 +711,8 @@
         sService = asInterface(b);
         return sService;
     }
-    
+
+    @Override
     public void noteResumeComponent(ComponentName componentName) {
         enforceCallingPermission();
         String pkgName;
@@ -720,7 +721,7 @@
                     ((pkgName = componentName.getPackageName()) == null)) {
                 return;
             }
-            
+
             final boolean samePackage = pkgName.equals(mLastResumedPkg);
             if (mIsResumed) {
                 if (mLastResumedPkg != null) {
@@ -734,14 +735,14 @@
                     }
                 }
             }
-            
+
             final boolean sameComp = samePackage
                     && componentName.getClassName().equals(mLastResumedComp);
-            
+
             mIsResumed = true;
             mLastResumedPkg = pkgName;
             mLastResumedComp = componentName.getClassName();
-            
+
             if (localLOGV) Slog.i(TAG, "started component:" + pkgName);
             PkgUsageStatsExtended pus = mStats.get(pkgName);
             if (pus == null) {
@@ -762,9 +763,10 @@
         }
     }
 
+    @Override
     public void notePauseComponent(ComponentName componentName) {
         enforceCallingPermission();
-        
+
         synchronized (mStatsLock) {
             String pkgName;
             if ((componentName == null) ||
@@ -777,9 +779,9 @@
                 return;
             }
             mIsResumed = false;
-            
+
             if (localLOGV) Slog.i(TAG, "paused component:"+pkgName);
-        
+
             PkgUsageStatsExtended pus = mStats.get(pkgName);
             if (pus == null) {
                 // Weird some error here
@@ -788,11 +790,12 @@
             }
             pus.updatePause();
         }
-        
+
         // Persist current data to file if needed.
         writeStatsToFile(false, false);
     }
-    
+
+    @Override
     public void noteLaunchTime(ComponentName componentName, int millis) {
         enforceCallingPermission();
         String pkgName;
@@ -800,10 +803,10 @@
                 ((pkgName = componentName.getPackageName()) == null)) {
             return;
         }
-        
+
         // Persist current data to file if needed.
         writeStatsToFile(false, false);
-        
+
         synchronized (mStatsLock) {
             PkgUsageStatsExtended pus = mStats.get(pkgName);
             if (pus != null) {
@@ -811,7 +814,7 @@
             }
         }
     }
-    
+
     public void noteFullyDrawnTime(ComponentName componentName, int millis) {
         enforceCallingPermission();
         String pkgName;
@@ -838,7 +841,8 @@
         mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
     }
-    
+
+    @Override
     public PkgUsageStats getPkgUsageStats(ComponentName componentName) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
@@ -858,7 +862,8 @@
             return new PkgUsageStats(pkgName, launchCount, usageTime, lastResumeTimes);
         }
     }
-    
+
+    @Override
     public PkgUsageStats[] getAllPkgUsageStats() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
@@ -884,8 +889,8 @@
             return retArr;
         }
     }
-    
-    static byte[] readFully(FileInputStream stream) throws java.io.IOException {
+
+    static byte[] readFully(FileInputStream stream) throws IOException {
         int pos = 0;
         int avail = stream.available();
         byte[] data = new byte[avail];
@@ -903,7 +908,7 @@
             }
         }
     }
-    
+
     private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput,
             boolean deleteAfterPrint, HashSet<String> packages) {
         List<String> fileList = getUsageStatsFileListFLOCK();
@@ -932,15 +937,12 @@
                     // Delete old file after collecting info only for checkin requests
                     dFile.delete();
                 }
-            } catch (FileNotFoundException e) {
-                Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file);
-                return;
             } catch (IOException e) {
                 Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file);
-            }      
+            }
         }
     }
-    
+
     private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw,
             String date, boolean isCompactOutput, HashSet<String> packages) {
         StringBuilder sb = new StringBuilder(512);
@@ -951,19 +953,19 @@
         } else {
             sb.append("Date: ");
         }
-        
+
         sb.append(date);
-        
+
         int vers = in.readInt();
         if (vers != VERSION) {
             sb.append(" (old data version)");
             pw.println(sb.toString());
             return;
         }
-        
+
         pw.println(sb.toString());
         int N = in.readInt();
-        
+
         while (N > 0) {
             N--;
             String pkgName = in.readString();
@@ -990,10 +992,10 @@
                     sb.append(activity);
                     TimeStats times = pus.mLaunchTimes.valueAt(i);
                     sb.append(',');
-                    sb.append(times.count);
+                    sb.append(times.mCount);
                     for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) {
                         sb.append(",");
-                        sb.append(times.times[j]);
+                        sb.append(times.mTimes[j]);
                     }
                     sb.append('\n');
                 }
@@ -1005,7 +1007,7 @@
                     TimeStats times = pus.mFullyDrawnTimes.valueAt(i);
                     for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) {
                         sb.append(",");
-                        sb.append(times.times[j]);
+                        sb.append(times.mTimes[j]);
                     }
                     sb.append('\n');
                 }
@@ -1025,26 +1027,26 @@
                     sb.append(pus.mLaunchTimes.keyAt(i));
                     TimeStats times = pus.mLaunchTimes.valueAt(i);
                     sb.append(": ");
-                    sb.append(times.count);
+                    sb.append(times.mCount);
                     sb.append(" starts");
                     int lastBin = 0;
                     for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) {
-                        if (times.times[j] != 0) {
+                        if (times.mTimes[j] != 0) {
                             sb.append(", ");
                             sb.append(lastBin);
                             sb.append('-');
                             sb.append(LAUNCH_TIME_BINS[j]);
                             sb.append("ms=");
-                            sb.append(times.times[j]);
+                            sb.append(times.mTimes[j]);
                         }
                         lastBin = LAUNCH_TIME_BINS[j];
                     }
-                    if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
+                    if (times.mTimes[NUM_LAUNCH_TIME_BINS-1] != 0) {
                         sb.append(", ");
                         sb.append(">=");
                         sb.append(lastBin);
                         sb.append("ms=");
-                        sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
+                        sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]);
                     }
                     sb.append('\n');
                 }
@@ -1057,7 +1059,7 @@
                     boolean needComma = false;
                     int lastBin = 0;
                     for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) {
-                        if (times.times[j] != 0) {
+                        if (times.mTimes[j] != 0) {
                             if (needComma) {
                                 sb.append(", ");
                             } else {
@@ -1067,27 +1069,27 @@
                             sb.append('-');
                             sb.append(LAUNCH_TIME_BINS[j]);
                             sb.append("ms=");
-                            sb.append(times.times[j]);
+                            sb.append(times.mTimes[j]);
                         }
                         lastBin = LAUNCH_TIME_BINS[j];
                     }
-                    if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
+                    if (times.mTimes[NUM_LAUNCH_TIME_BINS-1] != 0) {
                         if (needComma) {
                             sb.append(", ");
                         }
                         sb.append(">=");
                         sb.append(lastBin);
                         sb.append("ms=");
-                        sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
+                        sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]);
                     }
                     sb.append('\n');
                 }
             }
-            
+
             pw.write(sb.toString());
         }
     }
-    
+
     /**
      * Searches array of arguments for the specified string
      * @param args array of argument strings
@@ -1104,7 +1106,7 @@
         }
         return false;
     }
-    
+
     /**
      * Searches array of arguments for the specified string's data
      * @param args array of argument strings
@@ -1123,11 +1125,11 @@
         }
         return null;
     }
-    
-    @Override
+
     /*
-     * The data persisted to file is parsed and the stats are computed. 
+     * The data persisted to file is parsed and the stats are computed.
      */
+    @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingPermission(android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -1141,23 +1143,23 @@
         final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c");
         final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d");
         final String rawPackages = scanArgsData(args, "--packages");
-        
+
         // Make sure the current stats are written to the file.  This
         // doesn't need to be done if we are deleting files after printing,
-        // since it that case we won't print the current stats.
+        // since in that case we won't print the current stats.
         if (!deleteAfterPrint) {
             writeStatsToFile(true, false);
         }
-        
+
         HashSet<String> packages = null;
         if (rawPackages != null) {
             if (!"*".equals(rawPackages)) {
                 // A * is a wildcard to show all packages.
                 String[] names = rawPackages.split(",");
+                if (names.length != 0) {
+                    packages = new HashSet<String>();
+                }
                 for (String n : names) {
-                    if (packages == null) {
-                        packages = new HashSet<String>();
-                    }
                     packages.add(n);
                 }
             }
@@ -1167,7 +1169,7 @@
             Slog.w(TAG, "Checkin without packages");
             return;
         }
-        
+
         synchronized (mFileLock) {
             collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages);
         }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 026fd296..1b40cdf 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -411,6 +411,7 @@
 
         if (!factoryTest) {
             intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+            intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
             context.registerReceiver(mBootCompletedReceiver, intentFilter);
         }
 
diff --git a/services/core/java/com/android/server/hdmi/FeatureAction.java b/services/core/java/com/android/server/hdmi/FeatureAction.java
new file mode 100644
index 0000000..296cc5b
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/FeatureAction.java
@@ -0,0 +1,211 @@
+/*
+ * 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;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Encapsulates a sequence of CEC/MHL command exchange for a certain feature.
+ *
+ * <p>Many CEC/MHL features are accomplished by CEC devices on the bus exchanging
+ * more than one command. {@link FeatureAction} represents the life cycle of the communication,
+ * manages the state as the process progresses, and if necessary, returns the result
+ * to the caller which initiates the action, through the callback given at the creation
+ * of the object. All the actual action classes inherit FeatureAction.
+ *
+ * <p>More than one FeatureAction objects can be up and running simultaneously,
+ * maintained by {@link HdmiControlService}. Each action is passed a new command
+ * arriving from the bus, and either consumes it if the command is what the action expects,
+ * or yields it to other action.
+ *
+ * Declared as package private, accessed by {@link HdmiControlService} only.
+ */
+abstract class FeatureAction {
+
+    private static final String TAG = "FeatureAction";
+
+    // Timer handler message used for timeout event
+    protected static final int MSG_TIMEOUT = 100;
+
+    // Default timeout for the incoming command to arrive in response to a request
+    protected static final int TIMEOUT_MS = 1000;
+
+    // Default state used in common by all the feature actions.
+    protected static final int STATE_NONE = 0;
+
+    // Internal state indicating the progress of action.
+    protected int mState = STATE_NONE;
+
+    protected final HdmiControlService mService;
+
+    // Logical address of the device for which the feature action is taken. The commands
+    // generated in an action all use this field as source address.
+    protected final int mSourceAddress;
+
+    // Timer that manages timeout events.
+    protected ActionTimer mActionTimer;
+
+    FeatureAction(HdmiControlService service, int sourceAddress) {
+        mService = service;
+        mSourceAddress = sourceAddress;
+        mActionTimer = createActionTimer(service.getServiceLooper());
+    }
+
+    @VisibleForTesting
+    void setActionTimer(ActionTimer actionTimer) {
+        mActionTimer = actionTimer;
+    }
+
+    /**
+     * Called right after the action is created. Initialization or first step to take
+     * for the action can be done in this method.
+     *
+     * @return true if the operation is successful; otherwise false.
+     */
+    abstract boolean start();
+
+    /**
+     * Process the command. Called whenever a new command arrives.
+     *
+     * @param cmd command to process
+     * @return true if the command was consumed in the process; Otherwise false, which
+     *          indicates that the command shall be handled by other actions.
+     */
+    abstract boolean processCommand(HdmiCecMessage cmd);
+
+    /**
+     * Called when the action should handle the timer event it created before.
+     *
+     * <p>CEC standard mandates each command transmission should be responded within
+     * certain period of time. The method is called when the timer it created as it transmitted
+     * a command gets expired. Inner logic should take an appropriate action.
+     *
+     * @param state the state associated with the time when the timer was created
+     */
+    abstract void handleTimerEvent(int state);
+
+    /**
+     * Timer handler interface used for FeatureAction classes.
+     */
+    interface ActionTimer {
+        /**
+         * Send a timer message.
+         *
+         * Also carries the state of the action when the timer is created. Later this state is
+         * compared to the one the action is in when it receives the timer to let the action tell
+         * the right timer to handle.
+         *
+         * @param state state of the action is in
+         * @param delayMillis amount of delay for the timer
+         */
+        void sendTimerMessage(int state, long delayMillis);
+    }
+
+    private class ActionTimerHandler extends Handler implements ActionTimer {
+
+        public ActionTimerHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void sendTimerMessage(int state, long delayMillis) {
+            sendMessageDelayed(obtainMessage(MSG_TIMEOUT, state), delayMillis);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case MSG_TIMEOUT:
+                handleTimerEvent(msg.arg1);
+                break;
+            default:
+                Slog.w(TAG, "Unsupported message:" + msg.what);
+                break;
+            }
+        }
+    }
+
+    private ActionTimer createActionTimer(Looper looper) {
+        return new ActionTimerHandler(looper);
+    }
+
+    // Add a new timer. The timer event will come to mActionTimer.handleMessage() in
+    // delayMillis.
+    protected void addTimer(int state, int delayMillis) {
+        mActionTimer.sendTimerMessage(state, delayMillis);
+    }
+
+    static HdmiCecMessage buildCommand(int src, int dst, int opcode, byte[] params) {
+        return new HdmiCecMessage(src, dst, opcode, params);
+    }
+
+    // Build a CEC command that does not have parameter.
+    static HdmiCecMessage buildCommand(int src, int dst, int opcode) {
+        return new HdmiCecMessage(src, dst, opcode, HdmiCecMessage.EMPTY_PARAM);
+    }
+
+    protected final void sendCommand(HdmiCecMessage cmd) {
+        mService.sendCecCommand(cmd);
+    }
+
+    protected final void sendBroadcastCommand(int opcode, byte[] param) {
+        sendCommand(buildCommand(mSourceAddress, HdmiCec.ADDR_BROADCAST, opcode, param));
+    }
+
+    /**
+     * Finish up the action. Reset the state, and remove itself from the action queue.
+     */
+    protected void finish() {
+        mState = STATE_NONE;
+        removeAction(this);
+    }
+
+    /**
+     * Remove the action from the action queue. This is called after the action finishes
+     * its role.
+     *
+     * @param action
+     */
+    private void removeAction(FeatureAction action) {
+        mService.removeAction(action);
+    }
+
+    // Utility methods for generating parameter byte arrays for CEC commands.
+    protected static byte[] uiCommandParam(int uiCommand) {
+        return new byte[] {(byte) uiCommand};
+    }
+
+    protected static byte[] physicalAddressParam(int physicalAddress) {
+        return new byte[] {
+                (byte) ((physicalAddress >> 8) & 0xFF),
+                (byte) (physicalAddress & 0xFF)
+        };
+    }
+
+    protected static byte[] pathPairParam(int oldPath, int newPath) {
+        return new byte[] {
+                (byte) ((oldPath >> 8) & 0xFF), (byte) (oldPath & 0xFF),
+                (byte) ((newPath >> 8) & 0xFF), (byte) (newPath & 0xFF)
+        };
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 5f07108..c87fc99 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -16,9 +16,20 @@
 
 package com.android.server.hdmi;
 
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.hardware.hdmi.HdmiCecMessage;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import libcore.util.EmptyArray;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Manages HDMI-CEC command and behaviors. It converts user's command into CEC command
@@ -32,17 +43,48 @@
 class HdmiCecController {
     private static final String TAG = "HdmiCecController";
 
+    private static final byte[] EMPTY_BODY = EmptyArray.BYTE;
+
+    // A message to pass cec send command to IO looper.
+    private static final int MSG_SEND_CEC_COMMAND = 1;
+    // A message to delegate logical allocation to IO looper.
+    private static final int MSG_ALLOCATE_LOGICAL_ADDRESS = 2;
+
+    // Message types to handle incoming message in main service looper.
+    private final static int MSG_RECEIVE_CEC_COMMAND = 1;
+    // A message to report allocated logical address to main control looper.
+    private final static int MSG_REPORT_LOGICAL_ADDRESS = 2;
+
+    // TODO: move these values to HdmiCec.java once make it internal constant class.
+    // CEC's ABORT reason values.
+    private static final int ABORT_UNRECOGNIZED_MODE = 0;
+    private static final int ABORT_NOT_IN_CORRECT_MODE = 1;
+    private static final int ABORT_CANNOT_PROVIDE_SOURCE = 2;
+    private static final int ABORT_INVALID_OPERAND = 3;
+    private static final int ABORT_REFUSED = 4;
+    private static final int ABORT_UNABLE_TO_DETERMINE = 5;
+
+    private static final int NUM_LOGICAL_ADDRESS = 16;
+
+    // TODO: define other constants for errors.
+    private static final int ERROR_SUCCESS = 0;
+
     // Handler instance to process synchronous I/O (mainly send) message.
     private Handler mIoHandler;
 
     // Handler instance to process various messages coming from other CEC
     // device or issued by internal state change.
-    private Handler mMessageHandler;
+    private Handler mControlHandler;
 
     // Stores the pointer to the native implementation of the service that
     // interacts with HAL.
     private long mNativePtr;
 
+    // Map-like container of all cec devices. A logical address of device is
+    // used as key of container.
+    private final SparseArray<HdmiCecDeviceInfo> mDeviceInfos =
+            new SparseArray<HdmiCecDeviceInfo>();
+
     // Private constructor.  Use HdmiCecController.create().
     private HdmiCecController() {
     }
@@ -52,14 +94,12 @@
      * inner device or has no device it will return {@code null}.
      *
      * <p>Declared as package-private, accessed by {@link HdmiControlService} only.
-     *
-     * @param ioLooper a Looper instance to handle IO (mainly send message) operation.
-     * @param messageHandler a message handler that processes a message coming from other
-     *                       CEC compatible device or callback of internal state change.
+     * @param service {@link HdmiControlService} instance used to create internal handler
+     *                and to pass callback for incoming message or event.
      * @return {@link HdmiCecController} if device is initialized successfully. Otherwise,
      *         returns {@code null}.
      */
-    static HdmiCecController create(Looper ioLooper, Handler messageHandler) {
+    static HdmiCecController create(HdmiControlService service) {
         HdmiCecController handler = new HdmiCecController();
         long nativePtr = nativeInit(handler);
         if (nativePtr == 0L) {
@@ -67,28 +107,263 @@
             return null;
         }
 
-        handler.init(ioLooper, messageHandler, nativePtr);
+        handler.init(service, nativePtr);
         return handler;
     }
 
-    private void init(Looper ioLooper, Handler messageHandler, long nativePtr) {
-        mIoHandler = new Handler(ioLooper) {
-                @Override
-            public void handleMessage(Message msg) {
-                // TODO: Call native sendMessage.
-            }
-        };
-
-        mMessageHandler = messageHandler;
-        mNativePtr = nativePtr;
+    /**
+     * Interface to report allocated logical address.
+     */
+    interface AllocateLogicalAddressCallback {
+        /**
+         * Called when a new logical address is allocated.
+         *
+         * @param deviceType requested device type to allocate logical address
+         * @param logicalAddress allocated logical address. If it is
+         *                       {@link HdmiCec#ADDR_UNREGISTERED}, it means that
+         *                       it failed to allocate logical address for the given device type
+         */
+        void onAllocated(int deviceType, int logicalAddress);
     }
 
     /**
-     * Called by native when an HDMI-CEC message arrived.
+     * Allocate a new logical address of the given device type. Allocated
+     * address will be reported through {@link AllocateLogicalAddressCallback}.
+     *
+     * <p> Declared as package-private, accessed by {@link HdmiControlService} only.
+     *
+     * @param deviceType type of device to used to determine logical address
+     * @param preferredAddress a logical address preferred to be allocated.
+     *                         If sets {@link HdmiCec#ADDR_UNREGISTERED}, scans
+     *                         the smallest logical address matched with the given device type.
+     *                         Otherwise, scan address will start from {@code preferredAddress}
+     * @param callback callback interface to report allocated logical address to caller
      */
-    private void handleMessage(int srcAddress, int dstAddres, int opcode, byte[] params) {
-        // TODO: Translate message and delegate it to main message handler.
+    void allocateLogicalAddress(int deviceType, int preferredAddress,
+            AllocateLogicalAddressCallback callback) {
+        Message msg = mIoHandler.obtainMessage(MSG_ALLOCATE_LOGICAL_ADDRESS);
+        msg.arg1 = deviceType;
+        msg.arg2 = preferredAddress;
+        msg.obj = callback;
+        mIoHandler.sendMessage(msg);
+    }
+
+    private static byte[] buildBody(int opcode, byte[] params) {
+        byte[] body = new byte[params.length + 1];
+        body[0] = (byte) opcode;
+        System.arraycopy(params, 0, body, 1, params.length);
+        return body;
+    }
+
+    private final class IoHandler extends Handler {
+        private IoHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SEND_CEC_COMMAND:
+                    HdmiCecMessage cecMessage = (HdmiCecMessage) msg.obj;
+                    byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams());
+                    nativeSendCecCommand(mNativePtr, cecMessage.getSource(),
+                            cecMessage.getDestination(), body);
+                    break;
+                case MSG_ALLOCATE_LOGICAL_ADDRESS:
+                    int deviceType = msg.arg1;
+                    int preferredAddress = msg.arg2;
+                    AllocateLogicalAddressCallback callback =
+                            (AllocateLogicalAddressCallback) msg.obj;
+                    handleAllocateLogicalAddress(deviceType, preferredAddress, callback);
+                    break;
+                default:
+                    Slog.w(TAG, "Unsupported CEC Io request:" + msg.what);
+                    break;
+            }
+        }
+
+        private void handleAllocateLogicalAddress(int deviceType, int preferredAddress,
+                AllocateLogicalAddressCallback callback) {
+            int startAddress = preferredAddress;
+            // If preferred address is "unregistered", start_index will be the smallest
+            // address matched with the given device type.
+            if (preferredAddress == HdmiCec.ADDR_UNREGISTERED) {
+                for (int i = 0; i < NUM_LOGICAL_ADDRESS; ++i) {
+                    if (deviceType == HdmiCec.getTypeFromAddress(i)) {
+                        startAddress = i;
+                        break;
+                    }
+                }
+            }
+
+            int logcialAddress = HdmiCec.ADDR_UNREGISTERED;
+            // Iterates all possible addresses which has the same device type.
+            for (int i = 0; i < NUM_LOGICAL_ADDRESS; ++i) {
+                int curAddress = (startAddress + i) % NUM_LOGICAL_ADDRESS;
+                if (curAddress != HdmiCec.ADDR_UNREGISTERED
+                        && deviceType == HdmiCec.getTypeFromAddress(i)) {
+                    // <Polling Message> is a message which has empty body and
+                    // uses same address for both source and destination address.
+                    // If sending <Polling Message> failed (NAK), it becomes
+                    // new logical address for the device because no device uses
+                    // it as logical address of the device.
+                    int error = nativeSendCecCommand(mNativePtr, curAddress, curAddress,
+                            EMPTY_BODY);
+                    if (error != ERROR_SUCCESS) {
+                        logcialAddress = curAddress;
+                        break;
+                    }
+                }
+            }
+
+            Message msg = mControlHandler.obtainMessage(MSG_REPORT_LOGICAL_ADDRESS);
+            msg.arg1 = deviceType;
+            msg.arg2 = logcialAddress;
+            msg.obj = callback;
+            mControlHandler.sendMessage(msg);
+        }
+    }
+
+    private final class ControlHandler extends Handler {
+        private ControlHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_RECEIVE_CEC_COMMAND:
+                    // TODO: delegate it to HdmiControl service.
+                    onReceiveCommand((HdmiCecMessage) msg.obj);
+                    break;
+                case MSG_REPORT_LOGICAL_ADDRESS:
+                    int deviceType = msg.arg1;
+                    int logicalAddress = msg.arg2;
+                    AllocateLogicalAddressCallback callback =
+                            (AllocateLogicalAddressCallback) msg.obj;
+                    callback.onAllocated(deviceType, logicalAddress);
+                    break;
+                default:
+                    Slog.i(TAG, "Unsupported message type:" + msg.what);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Add a new {@link HdmiCecDeviceInfo}. It returns old device info which has the same
+     * logical address as new device info's.
+     *
+     * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     *
+     * @param deviceInfo a new {@link HdmiCecDeviceInfo} to be added.
+     * @return {@code null} if it is new device. Otherwise, returns old {@HdmiCecDeviceInfo}
+     *         that has the same logical address as new one has.
+     */
+    HdmiCecDeviceInfo addDeviceInfo(HdmiCecDeviceInfo deviceInfo) {
+        HdmiCecDeviceInfo oldDeviceInfo = getDeviceInfo(deviceInfo.getLogicalAddress());
+        if (oldDeviceInfo != null) {
+            removeDeviceInfo(deviceInfo.getLogicalAddress());
+        }
+        mDeviceInfos.append(deviceInfo.getLogicalAddress(), deviceInfo);
+        return oldDeviceInfo;
+    }
+
+    /**
+     * Remove a device info corresponding to the given {@code logicalAddress}.
+     * It returns removed {@link HdmiCecDeviceInfo} if exists.
+     *
+     * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     *
+     * @param logicalAddress logical address of device to be removed
+     * @return removed {@link HdmiCecDeviceInfo} it exists. Otherwise, returns {@code null}
+     */
+    HdmiCecDeviceInfo removeDeviceInfo(int logicalAddress) {
+        HdmiCecDeviceInfo deviceInfo = mDeviceInfos.get(logicalAddress);
+        if (deviceInfo != null) {
+            mDeviceInfos.remove(logicalAddress);
+        }
+        return deviceInfo;
+    }
+
+    /**
+     * Return a list of all {@HdmiCecDeviceInfo}.
+     *
+     * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     */
+    List<HdmiCecDeviceInfo> getDeviceInfoList() {
+        List<HdmiCecDeviceInfo> deviceInfoList = new ArrayList<HdmiCecDeviceInfo>(
+                mDeviceInfos.size());
+        for (int i = 0; i < mDeviceInfos.size(); ++i) {
+            deviceInfoList.add(mDeviceInfos.valueAt(i));
+        }
+        return deviceInfoList;
+    }
+
+    /**
+     * Return a {@link HdmiCecDeviceInfo} corresponding to the given {@code logicalAddress}.
+     *
+     * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     *
+     * @param logicalAddress logical address to be retrieved
+     * @return {@link HdmiCecDeviceInfo} matched with the given {@code logicalAddress}.
+     *         Returns null if no logical address matched
+     */
+    HdmiCecDeviceInfo getDeviceInfo(int logicalAddress) {
+        return mDeviceInfos.get(logicalAddress);
+    }
+
+    private void init(HdmiControlService service, long nativePtr) {
+        mIoHandler = new IoHandler(service.getServiceLooper());
+        mControlHandler = new ControlHandler(service.getServiceLooper());
+        mNativePtr = nativePtr;
+    }
+
+    private void onReceiveCommand(HdmiCecMessage message) {
+        // TODO: Handle message according to opcode type.
+
+        // TODO: Use device's source address for broadcast message.
+        int sourceAddress = message.getDestination() != HdmiCec.ADDR_BROADCAST ?
+                message.getDestination() : 0;
+        // Reply <Feature Abort> to initiator (source) for all requests.
+        sendFeatureAbort(sourceAddress, message.getSource(), message.getOpcode(),
+                ABORT_REFUSED);
+    }
+
+    private void sendFeatureAbort(int srcAddress, int destAddress, int originalOpcode,
+            int reason) {
+        byte[] params = new byte[2];
+        params[0] = (byte) originalOpcode;
+        params[1] = (byte) reason;
+
+        HdmiCecMessage cecMessage = new HdmiCecMessage(srcAddress, destAddress,
+                HdmiCec.MESSAGE_FEATURE_ABORT, params);
+        Message message = mIoHandler.obtainMessage(MSG_SEND_CEC_COMMAND, cecMessage);
+        mIoHandler.sendMessage(message);
+    }
+
+    /**
+     * Called by native when incoming CEC message arrived.
+     */
+    private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) {
+        byte opcode = body[0];
+        byte params[] = Arrays.copyOfRange(body, 1, body.length);
+        HdmiCecMessage cecMessage = new HdmiCecMessage(srcAddress, dstAddress, opcode, params);
+
+        // Delegate message to main handler so that it handles in main thread.
+        Message message = mControlHandler.obtainMessage(
+                MSG_RECEIVE_CEC_COMMAND, cecMessage);
+        mControlHandler.sendMessage(message);
+    }
+
+    /**
+     * Called by native when a hotplug event issues.
+     */
+    private void handleHotplug(boolean connected) {
+        // TODO: Delegate event to main message handler.
     }
 
     private static native long nativeInit(HdmiCecController handler);
+    private static native int nativeSendCecCommand(long contollerPtr, int srcAddress,
+            int dstAddress, byte[] body);
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 56c5b49..f99c717 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -18,9 +18,10 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
-import android.os.Handler;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.hardware.hdmi.HdmiCecMessage;
 import android.os.HandlerThread;
-import android.os.Message;
+import android.os.Looper;
 import android.util.Slog;
 
 import com.android.server.SystemService;
@@ -37,14 +38,6 @@
     // and sparse call it shares a thread to handle IO operations.
     private final HandlerThread mIoThread = new HandlerThread("Hdmi Control Io Thread");
 
-    // Main handler class to handle incoming message from each controller.
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            // TODO: Add handler for each message type.
-        }
-    };
-
     @Nullable
     private HdmiCecController mCecController;
 
@@ -57,14 +50,70 @@
 
     @Override
     public void onStart() {
-        mCecController = HdmiCecController.create(mIoThread.getLooper(), mHandler);
+        mCecController = HdmiCecController.create(this);
         if (mCecController == null) {
             Slog.i(TAG, "Device does not support HDMI-CEC.");
         }
 
-        mMhlController = HdmiMhlController.create(mIoThread.getLooper(), mHandler);
+        mMhlController = HdmiMhlController.create(this);
         if (mMhlController == null) {
             Slog.i(TAG, "Device does not support MHL-control.");
         }
     }
+
+    /**
+     * Returns {@link Looper} for IO operation.
+     *
+     * <p>Declared as package-private.
+     */
+    Looper getIoLooper() {
+        return mIoThread.getLooper();
+    }
+
+    /**
+     * Returns {@link Looper} of main thread. Use this {@link Looper} instance
+     * for tasks that are running on main service thread.
+     *
+     * <p>Declared as package-private.
+     */
+    Looper getServiceLooper() {
+        return Looper.myLooper();
+    }
+
+    /**
+     * Add a new {@link FeatureAction} to the action queue.
+     *
+     * @param action {@link FeatureAction} to add
+     */
+    void addAction(FeatureAction action) {
+        // TODO: Implement this.
+    }
+
+
+    /**
+     * Remove the given {@link FeatureAction} object from the action queue.
+     *
+     * @param action {@link FeatureAction} to add
+     */
+    void removeAction(FeatureAction action) {
+        // TODO: Implement this.
+    }
+
+    /**
+     * Transmit a CEC command to CEC bus.
+     *
+     * @param command CEC command to send out
+     */
+    void sendCecCommand(HdmiCecMessage command) {
+        // TODO: Implement this.
+    }
+
+    /**
+     * Add a new {@link HdmiCecDeviceInfo} to controller.
+     *
+     * @param deviceInfo new device information object to add
+     */
+    void addDeviceInfo(HdmiCecDeviceInfo deviceInfo) {
+        // TODO: Implement this.
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
new file mode 100644
index 0000000..c84a067
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.util.Slog;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Feature action that discovers the information of a newly found logical device.
+ *
+ * This action is created when receiving &lt;Report Physical Address&gt;, a CEC command a newly
+ * connected HDMI-CEC device broadcasts to announce its advent. Additional commands are issued in
+ * this action to gather more information on the device such as OSD name and device vendor ID.
+ *
+ * <p>The result is made in the form of {@link HdmiCecDeviceInfo} object, and passed to service
+ * for the management through its life cycle.
+ *
+ * <p>Package-private, accessed by {@link HdmiControlService} only.
+ */
+final class NewDeviceAction extends FeatureAction {
+
+    private static final String TAG = "NewDeviceAction";
+
+    // State in which the action sent <Give OSD Name> and is waiting for <Set OSD Name>
+    // that contains the name of the device for display on screen.
+    static final int STATE_WAITING_FOR_SET_OSD_NAME = 1;
+
+    // State in which the action sent <Give Device Vendor ID> and is waiting for
+    // <Device Vendor ID> that contains the vendor ID of the device.
+    static final int STATE_WAITING_FOR_DEVICE_VENDOR_ID = 2;
+
+    private final int mDeviceLogicalAddress;
+    private final int mDevicePhysicalAddress;
+
+    private int mVendorId;
+    private String mDisplayName;
+
+    /**
+     * Constructor.
+     *
+     * @param service {@link HdmiControlService} instance
+     * @param sourceAddress logical address to be used as source address
+     * @param deviceLogicalAddress logical address of the device in interest
+     * @param devicePhysicalAddress physical address of the device in interest
+     */
+    NewDeviceAction(HdmiControlService service, int sourceAddress, int deviceLogicalAddress,
+            int devicePhysicalAddress) {
+        super(service, sourceAddress);
+        mDeviceLogicalAddress = deviceLogicalAddress;
+        mDevicePhysicalAddress = devicePhysicalAddress;
+        mVendorId = HdmiCec.UNKNOWN_VENDOR_ID;
+    }
+
+    @Override
+    public boolean start() {
+        sendCommand(
+                buildCommand(mSourceAddress, mDeviceLogicalAddress, HdmiCec.MESSAGE_GET_OSD_NAME));
+        mState = STATE_WAITING_FOR_SET_OSD_NAME;
+        addTimer(mState, TIMEOUT_MS);
+        return true;
+    }
+
+    @Override
+    public boolean processCommand(HdmiCecMessage cmd) {
+        // For the logical device in interest, we want two more pieces of information -
+        // osd name and vendor id. They are requested in sequence. In case we don't
+        // get the expected responses (either by timeout or by receiving <feature abort> command),
+        // set them to a default osd name and unknown vendor id respectively.
+        int opcode = cmd.getOpcode();
+        int src = cmd.getSource();
+        byte[] params = cmd.getParams();
+
+        if (mDeviceLogicalAddress != src) {
+            return false;
+        }
+
+        if (mState == STATE_WAITING_FOR_SET_OSD_NAME) {
+            if (opcode == HdmiCec.MESSAGE_SET_OSD_NAME) {
+                try {
+                    mDisplayName = new String(params, "US-ASCII");
+                } catch (UnsupportedEncodingException e) {
+                    Slog.e(TAG, "Failed to get OSD name: " + e.getMessage());
+                }
+                mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID;
+                requestVendorId();
+                return true;
+            } else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
+                int requestOpcode = params[1];
+                if (requestOpcode == HdmiCec.MESSAGE_SET_OSD_NAME) {
+                    mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID;
+                    requestVendorId();
+                    return true;
+                }
+            }
+        } else if (mState == STATE_WAITING_FOR_DEVICE_VENDOR_ID) {
+            if (opcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) {
+                if (params.length == 3) {
+                    mVendorId = (params[0] << 16) + (params[1] << 8) + params[2];
+                } else {
+                    Slog.e(TAG, "Failed to get device vendor ID: ");
+                }
+                addDeviceInfo();
+                finish();
+                return true;
+            } else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
+                int requestOpcode = params[1];
+                if (requestOpcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) {
+                    addDeviceInfo();
+                    finish();
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private void requestVendorId() {
+        sendCommand(buildCommand(mSourceAddress, mDeviceLogicalAddress,
+                HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID));
+        addTimer(mState, TIMEOUT_MS);
+    }
+
+    private void addDeviceInfo() {
+        if (mDisplayName == null) {
+            mDisplayName = HdmiCec.getDefaultDeviceName(mDeviceLogicalAddress);
+        }
+        mService.addDeviceInfo(new HdmiCecDeviceInfo(
+                mDeviceLogicalAddress, mDevicePhysicalAddress,
+                HdmiCec.getTypeFromAddress(mDeviceLogicalAddress),
+                mVendorId, mDisplayName));
+    }
+
+    @Override
+    public void handleTimerEvent(int state) {
+        if (mState == STATE_NONE || mState != state) {
+            return;
+        }
+        if (state == STATE_WAITING_FOR_SET_OSD_NAME) {
+            // Osd name request timed out. Try vendor id
+            mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID;
+            requestVendorId();
+        } else if (state == STATE_WAITING_FOR_DEVICE_VENDOR_ID) {
+            // vendor id timed out. Go ahead creating the device info what we've got so far.
+            addDeviceInfo();
+            finish();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java
index 79f192d..09f1c567 100644
--- a/services/core/java/com/android/server/location/FlpHardwareProvider.java
+++ b/services/core/java/com/android/server/location/FlpHardwareProvider.java
@@ -69,6 +69,7 @@
             sSingletonInstance = new FlpHardwareProvider(context);
         }
 
+        nativeInit();
         return sSingletonInstance;
     }
 
@@ -96,6 +97,7 @@
     }
 
     public static boolean isSupported() {
+        nativeInit();
         return nativeIsSupported();
     }
 
@@ -216,9 +218,9 @@
     // Core members
     private static native void nativeClassInit();
     private static native boolean nativeIsSupported();
+    private static native void nativeInit();
 
     // FlpLocationInterface members
-    private native void nativeInit();
     private native int nativeGetBatchSize();
     private native void nativeStartBatching(int requestId, FusedBatchOptions options);
     private native void nativeUpdateBatchingOptions(int requestId, FusedBatchOptions optionsObject);
@@ -258,12 +260,10 @@
     public static final String GEOFENCING = "Geofencing";
 
     public IFusedLocationHardware getLocationHardware() {
-        nativeInit();
         return mLocationHardware;
     }
 
     public IFusedGeofenceHardware getGeofenceHardware() {
-        nativeInit();
         return mGeofenceHardwareService;
     }
 
diff --git a/services/core/java/com/android/server/media/MediaRouteProviderProxy.java b/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
index d314ea7..c4e2058 100644
--- a/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
@@ -36,6 +36,7 @@
 import android.util.Log;
 import android.util.Slog;
 
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
@@ -55,13 +56,12 @@
     private final String mId;
     private final ComponentName mComponentName;
     private final int mUserId;
+    // Interfaces declared in the manifest
+    private final ArrayList<String> mInterfaces = new ArrayList<String>();
+    private final ArrayList<RouteConnectionRecord> mConnections = new ArrayList<RouteConnectionRecord>();
+    private final Handler mHandler = new Handler();
 
     private Intent mBindIntent;
-    // Interfaces declared in the manifest
-    private ArrayList<String> mInterfaces;
-    private ArrayList<RouteConnectionRecord> mConnections = new ArrayList<RouteConnectionRecord>();
-    private Handler mHandler = new Handler();
-
     private IRouteProvider mBinder;
     private boolean mRunning;
     private boolean mInterested;
@@ -76,7 +76,9 @@
         mId = id;
         mComponentName = component;
         mUserId = uid;
-        mInterfaces = interfaces;
+        if (interfaces != null) {
+            mInterfaces.addAll(interfaces);
+        }
         mBindIntent = new Intent(RouteProviderService.SERVICE_INTERFACE);
         mBindIntent.setComponent(mComponentName);
     }
@@ -202,7 +204,7 @@
 
                     if (connection != null) {
                         RouteConnectionRecord record = new RouteConnectionRecord(
-                                connection);
+                                connection, mComponentName.getPackageName(), mUserId);
                         mConnections.add(record);
                         if (mRouteListener != null) {
                             mRouteListener.onRouteConnected(sessionId, route, request, record);
@@ -234,6 +236,19 @@
         return mId;
     }
 
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + mId + " " + this);
+        String indent = prefix + "  ";
+
+        pw.println(indent + "component=" + mComponentName.toString());
+        pw.println(indent + "user id=" + mUserId);
+        pw.println(indent + "interfaces=" + mInterfaces.toString());
+        pw.println(indent + "connections=" + mConnections.toString());
+        pw.println(indent + "running=" + mRunning);
+        pw.println(indent + "interested=" + mInterested);
+        pw.println(indent + "bound=" + mBound);
+    }
+
     private void updateBinding() {
         if (shouldBind()) {
             bind();
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index ac7f4f3..3dc17fc 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -40,12 +40,14 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
 import android.view.KeyEvent;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
@@ -226,6 +228,36 @@
         mService.sessionDied(this);
     }
 
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + mTag + " " + this);
+
+        final String indent = prefix + "  ";
+        pw.println(indent + "pid=" + mPid);
+        pw.println(indent + "info=" + mSessionInfo.toString());
+        pw.println(indent + "published=" + mIsPublished);
+        pw.println(indent + "transport controls enabled=" + mTransportPerformerEnabled);
+        pw.println(indent + "rating type=" + mRatingType);
+        pw.println(indent + "controllers: " + mControllerCallbacks.size());
+        pw.println(indent + "state=" + mPlaybackState.toString());
+        pw.println(indent + "metadata:" + getShortMetadataString());
+        pw.println(indent + "route requests {");
+        int size = mRequests.size();
+        for (int i = 0; i < size; i++) {
+            pw.println(indent + "  " + mRequests.get(i).toString());
+        }
+        pw.println(indent + "}");
+        pw.println(indent + "route=" + (mRoute == null ? null : mRoute.toString()));
+        pw.println(indent + "connection=" + (mConnection == null ? null : mConnection.toString()));
+        pw.println(indent + "params=" + (mRequest == null ? null : mRequest.toString()));
+    }
+
+    private String getShortMetadataString() {
+        int fields = mMetadata == null ? 0 : mMetadata.size();
+        String title = mMetadata == null ? null : mMetadata
+                .getString(MediaMetadata.METADATA_KEY_TITLE);
+        return "size=" + fields + ", title=" + title;
+    }
+
     private void onDestroy() {
         mService.destroySession(this);
     }
@@ -301,6 +333,34 @@
         }
     }
 
+    private PlaybackState getStateWithUpdatedPosition() {
+        PlaybackState state = mPlaybackState;
+        long duration = -1;
+        if (mMetadata != null && mMetadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
+            duration = mMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
+        }
+        PlaybackState result = null;
+        if (state != null) {
+            if (state.getState() == PlaybackState.PLAYSTATE_PLAYING
+                    || state.getState() == PlaybackState.PLAYSTATE_FAST_FORWARDING
+                    || state.getState() == PlaybackState.PLAYSTATE_REWINDING) {
+                long updateTime = state.getLastPositionUpdateTime();
+                if (updateTime > 0) {
+                    long position = (long) (state.getRate()
+                            * (SystemClock.elapsedRealtime() - updateTime)) + state.getPosition();
+                    if (duration >= 0 && position > duration) {
+                        position = duration;
+                    } else if (position < 0) {
+                        position = 0;
+                    }
+                    result = new PlaybackState(state);
+                    result.setState(state.getState(), position, state.getRate());
+                }
+            }
+        }
+        return result == null ? state : result;
+    }
+
     private final RouteConnectionRecord.Listener mConnectionListener
             = new RouteConnectionRecord.Listener() {
         @Override
@@ -603,7 +663,7 @@
 
         @Override
         public PlaybackState getPlaybackState() {
-            return mPlaybackState;
+            return getStateWithUpdatedPosition();
         }
 
         @Override
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index bc91370..107f6ad 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -16,7 +16,9 @@
 
 package com.android.server.media;
 
+import android.Manifest;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.media.routeprovider.RouteRequest;
 import android.media.session.ISession;
 import android.media.session.ISessionCallback;
@@ -30,13 +32,17 @@
 import android.util.Log;
 
 import com.android.server.SystemService;
+import com.android.server.Watchdog;
+import com.android.server.Watchdog.Monitor;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 /**
  * System implementation of MediaSessionManager
  */
-public class MediaSessionService extends SystemService {
+public class MediaSessionService extends SystemService implements Monitor {
     private static final String TAG = "MediaSessionService";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -69,6 +75,7 @@
     public void onStart() {
         publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl);
         mRouteProviderWatcher.start();
+        Watchdog.getInstance().addMonitor(this);
     }
 
     /**
@@ -114,14 +121,21 @@
         }
     }
 
+    @Override
+    public void monitor() {
+        synchronized (mLock) {
+            // Check for deadlock
+        }
+    }
+
     void sessionDied(MediaSessionRecord session) {
-        synchronized (mSessions) {
+        synchronized (mLock) {
             destroySessionLocked(session);
         }
     }
 
     void destroySession(MediaSessionRecord session) {
-        synchronized (mSessions) {
+        synchronized (mLock) {
             destroySessionLocked(session);
         }
     }
@@ -160,9 +174,7 @@
         } catch (RemoteException e) {
             throw new RuntimeException("Media Session owner died prematurely.", e);
         }
-        synchronized (mSessions) {
-            mSessions.add(session);
-        }
+        mSessions.add(session);
         if (DEBUG) {
             Log.d(TAG, "Created session for package " + packageName + " with tag " + tag);
         }
@@ -259,6 +271,36 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        @Override
+        public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+            if (getContext().checkCallingOrSelfPermission(Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump MediaSessionService from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid());
+                return;
+            }
+
+            pw.println("MEDIA SESSION SERVICE (dumpsys media_session)");
+            pw.println();
+
+            synchronized (mLock) {
+                int count = mSessions.size();
+                pw.println("Sessions - have " + count + " states:");
+                for (int i = 0; i < count; i++) {
+                    MediaSessionRecord record = mSessions.get(i);
+                    pw.println();
+                    record.dump(pw, "");
+                }
+                pw.println("Providers:");
+                count = mProviders.size();
+                for (int i = 0; i < count; i++) {
+                    MediaRouteProviderProxy provider = mProviders.get(i);
+                    provider.dump(pw, "");
+                }
+            }
+        }
     }
 
 }
diff --git a/services/core/java/com/android/server/media/RouteConnectionRecord.java b/services/core/java/com/android/server/media/RouteConnectionRecord.java
index 8da0f95..90ddf29 100644
--- a/services/core/java/com/android/server/media/RouteConnectionRecord.java
+++ b/services/core/java/com/android/server/media/RouteConnectionRecord.java
@@ -29,10 +29,14 @@
 public class RouteConnectionRecord {
     private static final String TAG = "RouteConnRecord";
     private final IRouteConnection mBinder;
+    private final String mPackageName;
+    private final int mUid;
     private Listener mListener;
 
-    public RouteConnectionRecord(IRouteConnection binder) {
+    public RouteConnectionRecord(IRouteConnection binder, String packageName, int uid) {
         mBinder = binder;
+        mPackageName = packageName;
+        mUid = uid;
     }
 
     /**
@@ -89,6 +93,12 @@
         }
     }
 
+    @Override
+    public String toString() {
+        return "RouteConnection { binder=" + mBinder.toString() + ", package=" + mPackageName
+                + ", uid=" + mUid + "}";
+    }
+
     /**
      * Listener to receive updates from the provider for this connection.
      */
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 855ae23..416a6b1 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -410,7 +410,7 @@
         }
 
         @Override
-        public void onImportanceChanged(int pid, int uid, int importance) {
+        public void onProcessStateChanged(int pid, int uid, int procState) {
         }
 
         @Override
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 5567944..d074565 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -16,6 +16,7 @@
 
 package com.android.server.notification;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Handler;
@@ -28,31 +29,31 @@
 import android.service.notification.ConditionProviderService;
 import android.service.notification.IConditionListener;
 import android.service.notification.IConditionProvider;
+import android.service.notification.ZenModeConfig;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Slog;
 
 import com.android.internal.R;
 
-import libcore.util.Objects;
-
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Arrays;
 
 public class ConditionProviders extends ManagedServices {
+    private static final Condition[] NO_CONDITIONS = new Condition[0];
 
     private final ZenModeHelper mZenModeHelper;
     private final ArrayMap<IBinder, IConditionListener> mListeners
             = new ArrayMap<IBinder, IConditionListener>();
-    private final ArrayMap<Uri, ManagedServiceInfo> mConditions
-            = new ArrayMap<Uri, ManagedServiceInfo>();
-
-    private Uri mCurrentConditionId;
+    private final ArrayList<ConditionRecord> mRecords = new ArrayList<ConditionRecord>();
 
     public ConditionProviders(Context context, Handler handler,
             UserProfiles userProfiles, ZenModeHelper zenModeHelper) {
         super(context, handler, new Object(), userProfiles);
         mZenModeHelper = zenModeHelper;
         mZenModeHelper.addCallback(new ZenModeHelperCallback());
+        loadZenConfig();
     }
 
     @Override
@@ -71,20 +72,13 @@
     public void dump(PrintWriter pw) {
         super.dump(pw);
         synchronized(mMutex) {
-            pw.print("    mCurrentConditionId="); pw.println(mCurrentConditionId);
             pw.print("    mListeners("); pw.print(mListeners.size()); pw.println("):");
             for (int i = 0; i < mListeners.size(); i++) {
                 pw.print("      "); pw.println(mListeners.keyAt(i));
             }
-            pw.print("    mConditions("); pw.print(mConditions.size()); pw.println("):");
-            for (int i = 0; i < mConditions.size(); i++) {
-                pw.print("      "); pw.print(mConditions.keyAt(i));
-                final ManagedServiceInfo info = mConditions.valueAt(i);
-                pw.print(" -> "); pw.print(info.component);
-                if (!mServices.contains(info)) {
-                    pw.print(" (orphan)");
-                }
-                pw.println();
+            pw.print("    mRecords("); pw.print(mRecords.size()); pw.println("):");
+            for (int i = 0; i < mRecords.size(); i++) {
+                pw.print("      "); pw.println(mRecords.get(i));
             }
         }
     }
@@ -95,29 +89,49 @@
     }
 
     @Override
-    protected void onServiceAdded(IInterface service) {
-        Slog.d(TAG, "onServiceAdded " + service);
-        final IConditionProvider provider = (IConditionProvider) service;
+    protected void onServiceAdded(ManagedServiceInfo info) {
+        Slog.d(TAG, "onServiceAdded " + info);
+        final IConditionProvider provider = provider(info);
         try {
             provider.onConnected();
         } catch (RemoteException e) {
             // we tried
         }
+        synchronized (mMutex) {
+            final int N = mRecords.size();
+            for(int i = 0; i < N; i++) {
+                final ConditionRecord r = mRecords.get(i);
+                if (!r.component.equals(info.component)) continue;
+                r.info = info;
+                // if automatic, auto-subscribe
+                if (r.isAutomatic) {
+                    try {
+                        final Uri id = r.id;
+                        if (DEBUG) Slog.d(TAG, "Auto-subscribing to configured condition " + id);
+                        provider.onSubscribe(id);
+                    } catch (RemoteException e) {
+                        // we tried
+                    }
+                }
+            }
+        }
     }
 
     @Override
     protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
         if (removed == null) return;
-        if (mCurrentConditionId != null) {
-            if (removed.equals(mConditions.get(mCurrentConditionId))) {
-                mCurrentConditionId = null;
+        for (int i = mRecords.size() - 1; i >= 0; i--) {
+            final ConditionRecord r = mRecords.get(i);
+            if (!r.component.equals(removed.component)) continue;
+            if (r.isManual) {
+                // removing the current manual condition, exit zen
                 mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF);
             }
-        }
-        for (int i = mConditions.size() - 1; i >= 0; i--) {
-            if (removed.equals(mConditions.valueAt(i))) {
-                mConditions.removeAt(i);
+            if (r.isAutomatic) {
+                // removing an automatic condition, exit zen
+                mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF);
             }
+            mRecords.remove(i);
         }
     }
 
@@ -127,14 +141,15 @@
         }
     }
 
-    public void requestZenModeConditions(IConditionListener callback, boolean requested) {
+    public void requestZenModeConditions(IConditionListener callback, int relevance) {
         synchronized(mMutex) {
             if (DEBUG) Slog.d(TAG, "requestZenModeConditions callback=" + callback
-                    + " requested=" + requested);
+                    + " relevance=" + Condition.relevanceToString(relevance));
             if (callback == null) return;
-            if (requested) {
+            relevance = relevance & (Condition.FLAG_RELEVANT_NOW | Condition.FLAG_RELEVANT_ALWAYS);
+            if (relevance != 0) {
                 mListeners.put(callback.asBinder(), callback);
-                requestConditionsLocked(Condition.FLAG_RELEVANT_NOW);
+                requestConditionsLocked(relevance);
             } else {
                 mListeners.remove(callback.asBinder());
                 if (mListeners.isEmpty()) {
@@ -144,25 +159,51 @@
         }
     }
 
+    private Condition[] validateConditions(String pkg, Condition[] conditions) {
+        if (conditions == null || conditions.length == 0) return null;
+        final int N = conditions.length;
+        final ArrayMap<Uri, Condition> valid = new ArrayMap<Uri, Condition>(N);
+        for (int i = 0; i < N; i++) {
+            final Uri id = conditions[i].id;
+            if (!Condition.isValidId(id, pkg)) {
+                Slog.w(TAG, "Ignoring condition from " + pkg + " for invalid id: " + id);
+                continue;
+            }
+            if (valid.containsKey(id)) {
+                Slog.w(TAG, "Ignoring condition from " + pkg + " for duplicate id: " + id);
+                continue;
+            }
+            valid.put(id, conditions[i]);
+        }
+        if (valid.size() == 0) return null;
+        if (valid.size() == N) return conditions;
+        final Condition[] rt = new Condition[valid.size()];
+        for (int i = 0; i < rt.length; i++) {
+            rt[i] = valid.valueAt(i);
+        }
+        return rt;
+    }
+
+    private ConditionRecord getRecordLocked(Uri id, ComponentName component) {
+        final int N = mRecords.size();
+        for (int i = 0; i < N; i++) {
+            final ConditionRecord r = mRecords.get(i);
+            if (r.id.equals(id) && r.component.equals(component)) {
+                return r;
+            }
+        }
+        final ConditionRecord r = new ConditionRecord(id, component);
+        mRecords.add(r);
+        return r;
+    }
+
     public void notifyConditions(String pkg, ManagedServiceInfo info, Condition[] conditions) {
         synchronized(mMutex) {
             if (DEBUG) Slog.d(TAG, "notifyConditions pkg=" + pkg + " info=" + info + " conditions="
                     + (conditions == null ? null : Arrays.asList(conditions)));
+            conditions = validateConditions(pkg, conditions);
             if (conditions == null || conditions.length == 0) return;
             final int N = conditions.length;
-            boolean valid = true;
-            for (int i = 0; i < N; i++) {
-                final Uri id = conditions[i].id;
-                if (!Condition.isValidId(id, pkg)) {
-                    Slog.w(TAG, "Ignoring conditions from " + pkg + " for invalid id: " + id);
-                    valid = false;
-                }
-            }
-            if (!valid) return;
-
-            for (int i = 0; i < N; i++) {
-                mConditions.put(conditions[i].id, info);
-            }
             for (IConditionListener listener : mListeners.values()) {
                 try {
                     listener.onConditionsReceived(conditions);
@@ -170,62 +211,154 @@
                     Slog.w(TAG, "Error sending conditions to listener " + listener, e);
                 }
             }
-            if (mCurrentConditionId != null) {
-                for (int i = 0; i < N; i++) {
-                    final Condition c = conditions[i];
-                    if (!c.id.equals(mCurrentConditionId)) continue;
-                    if (c.state == Condition.STATE_TRUE || c.state == Condition.STATE_ERROR) {
-                        triggerExitLocked(c.state == Condition.STATE_ERROR);
-                        return;
+            for (int i = 0; i < N; i++) {
+                final Condition c = conditions[i];
+                final ConditionRecord r = getRecordLocked(c.id, info.component);
+                r.info = info;
+                r.condition = c;
+                // if manual, exit zen if false (or failed)
+                if (r.isManual) {
+                    if (c.state == Condition.STATE_FALSE || c.state == Condition.STATE_ERROR) {
+                        final boolean failed = c.state == Condition.STATE_ERROR;
+                        if (failed) {
+                            Slog.w(TAG, "Exit zen: manual condition failed: " + c);
+                        } else if (DEBUG) {
+                            Slog.d(TAG, "Exit zen: manual condition false: " + c);
+                        }
+                        mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_OFF);
+                        unsubscribeLocked(r);
+                        r.isManual = false;
+                    }
+                }
+                // if automatic, exit zen if false (or failed), enter zen if true
+                if (r.isAutomatic) {
+                    if (c.state == Condition.STATE_FALSE || c.state == Condition.STATE_ERROR) {
+                        final boolean failed = c.state == Condition.STATE_ERROR;
+                        if (failed) {
+                            Slog.w(TAG, "Exit zen: automatic condition failed: " + c);
+                        } else if (DEBUG) {
+                            Slog.d(TAG, "Exit zen: automatic condition false: " + c);
+                        }
+                        mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_OFF);
+                    } else if (c.state == Condition.STATE_TRUE) {
+                        Slog.d(TAG, "Enter zen: automatic condition true: " + c);
+                        mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_ON);
                     }
                 }
             }
         }
     }
 
-    private void triggerExitLocked(boolean error) {
-        if (error) {
-            Slog.w(TAG, "Zen mode exit condition failed");
-        } else if (DEBUG) {
-            Slog.d(TAG, "Zen mode exit condition triggered");
-        }
-        mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_OFF);
-        unsubscribeLocked(mCurrentConditionId);
-        mCurrentConditionId = null;
-    }
-
     public void setZenModeCondition(Uri conditionId) {
+        if (DEBUG) Slog.d(TAG, "setZenModeCondition " + conditionId);
         synchronized(mMutex) {
-            if (DEBUG) Slog.d(TAG, "setZenModeCondition " + conditionId);
-            if (Objects.equal(mCurrentConditionId, conditionId)) return;
-
-            if (mCurrentConditionId != null) {
-                unsubscribeLocked(mCurrentConditionId);
-            }
-            if (conditionId != null) {
-                final ManagedServiceInfo info = mConditions.get(conditionId);
-                final IConditionProvider provider = provider(info);
-                if (provider == null) return;
-                try {
-                    provider.onSubscribe(conditionId);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Error subscribing to " + conditionId
-                            + " from " + info.component, e);
+            final int N = mRecords.size();
+            for (int i = 0; i < N; i++) {
+                final ConditionRecord r = mRecords.get(i);
+                final boolean idEqual = r.id.equals(conditionId);
+                if (r.isManual && !idEqual) {
+                    // was previous manual condition, unsubscribe
+                    unsubscribeLocked(r);
+                    r.isManual = false;
+                } else if (idEqual && !r.isManual) {
+                    // is new manual condition, subscribe
+                    subscribeLocked(r);
+                    r.isManual = true;
                 }
             }
-            mCurrentConditionId = conditionId;
         }
     }
 
-    private void unsubscribeLocked(Uri conditionId) {
-        final ManagedServiceInfo info = mConditions.get(mCurrentConditionId);
-        final IConditionProvider provider = provider(info);
-        if (provider == null) return;
-        try {
-            provider.onUnsubscribe(conditionId);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Error unsubscribing to " + conditionId + " from " + info.component, e);
+    private void subscribeLocked(ConditionRecord r) {
+        if (DEBUG) Slog.d(TAG, "subscribeLocked " + r);
+        final IConditionProvider provider = provider(r);
+        if (provider == null) {
+            Slog.w(TAG, "subscribeLocked: no provider");
+            return;
         }
+        try {
+            provider.onSubscribe(r.id);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Error subscribing to " + r, e);
+        }
+    }
+
+    private static <T> ArraySet<T> safeSet(T... items) {
+        final ArraySet<T> rt = new ArraySet<T>();
+        if (items == null || items.length == 0) return rt;
+        final int N = items.length;
+        for (int i = 0; i < N; i++) {
+            final T item = items[i];
+            if (item != null) {
+                rt.add(item);
+            }
+        }
+        return rt;
+    }
+
+    public void setAutomaticZenModeConditions(Uri[] conditionIds) {
+        setAutomaticZenModeConditions(conditionIds, true /*save*/);
+    }
+
+    private void setAutomaticZenModeConditions(Uri[] conditionIds, boolean save) {
+        if (DEBUG) Slog.d(TAG, "setAutomaticZenModeConditions "
+                + (conditionIds == null ? null : Arrays.asList(conditionIds)));
+        synchronized(mMutex) {
+            final ArraySet<Uri> newIds = safeSet(conditionIds);
+            final int N = mRecords.size();
+            boolean changed = false;
+            for (int i = 0; i < N; i++) {
+                final ConditionRecord r = mRecords.get(i);
+                final boolean automatic = newIds.contains(r.id);
+                if (!r.isAutomatic && automatic) {
+                    // subscribe to new automatic
+                    subscribeLocked(r);
+                    r.isAutomatic = true;
+                    changed = true;
+                } else if (r.isAutomatic && !automatic) {
+                    // unsubscribe from old automatic
+                    unsubscribeLocked(r);
+                    r.isAutomatic = false;
+                    changed = true;
+                }
+            }
+            if (save && changed) {
+                saveZenConfigLocked();
+            }
+        }
+    }
+
+    public Condition[] getAutomaticZenModeConditions() {
+        synchronized(mMutex) {
+            final int N = mRecords.size();
+            ArrayList<Condition> rt = null;
+            for (int i = 0; i < N; i++) {
+                final ConditionRecord r = mRecords.get(i);
+                if (r.isAutomatic && r.condition != null) {
+                    if (rt == null) rt = new ArrayList<Condition>();
+                    rt.add(r.condition);
+                }
+            }
+            return rt == null ? NO_CONDITIONS : rt.toArray(new Condition[rt.size()]);
+        }
+    }
+
+    private void unsubscribeLocked(ConditionRecord r) {
+        if (DEBUG) Slog.d(TAG, "unsubscribeLocked " + r);
+        final IConditionProvider provider = provider(r);
+        if (provider == null) {
+            Slog.w(TAG, "unsubscribeLocked: no provider");
+            return;
+        }
+        try {
+            provider.onUnsubscribe(r.id);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Error unsubscribing to " + r, e);
+        }
+    }
+
+    private static IConditionProvider provider(ConditionRecord r) {
+        return r == null ? null : provider(r.info);
     }
 
     private static IConditionProvider provider(ManagedServiceInfo info) {
@@ -244,20 +377,99 @@
         }
     }
 
+    private void loadZenConfig() {
+        final ZenModeConfig config = mZenModeHelper.getConfig();
+        if (config == null) {
+            if (DEBUG) Slog.d(TAG, "loadZenConfig: no config");
+            return;
+        }
+        synchronized (mMutex) {
+            if (config.conditionComponents == null || config.conditionIds == null
+                    || config.conditionComponents.length != config.conditionIds.length) {
+                if (DEBUG) Slog.d(TAG, "loadZenConfig: no conditions");
+                setAutomaticZenModeConditions(null, false /*save*/);
+                return;
+            }
+            final ArraySet<Uri> newIds = new ArraySet<Uri>();
+            final int N = config.conditionComponents.length;
+            for (int i = 0; i < N; i++) {
+                final ComponentName component = config.conditionComponents[i];
+                final Uri id = config.conditionIds[i];
+                if (component != null && id != null) {
+                    getRecordLocked(id, component);  // ensure record exists
+                    newIds.add(id);
+                }
+            }
+            if (DEBUG) Slog.d(TAG, "loadZenConfig: N=" + N);
+            setAutomaticZenModeConditions(newIds.toArray(new Uri[newIds.size()]), false /*save*/);
+        }
+    }
+
+    private void saveZenConfigLocked() {
+        ZenModeConfig config = mZenModeHelper.getConfig();
+        if (config == null) return;
+        config = config.copy();
+        final ArrayList<ConditionRecord> automatic = new ArrayList<ConditionRecord>();
+        final int automaticN = mRecords.size();
+        for (int i = 0; i < automaticN; i++) {
+            final ConditionRecord r = mRecords.get(i);
+            if (r.isAutomatic) {
+                automatic.add(r);
+            }
+        }
+        if (automatic.isEmpty()) {
+            config.conditionComponents = null;
+            config.conditionIds = null;
+        } else {
+            final int N = automatic.size();
+            config.conditionComponents = new ComponentName[N];
+            config.conditionIds = new Uri[N];
+            for (int i = 0; i < N; i++) {
+                final ConditionRecord r = automatic.get(i);
+                config.conditionComponents[i] = r.component;
+                config.conditionIds[i] = r.id;
+            }
+        }
+        if (DEBUG) Slog.d(TAG, "Setting zen config to: " + config);
+        mZenModeHelper.setConfig(config);
+    }
+
     private class ZenModeHelperCallback extends ZenModeHelper.Callback {
         @Override
+        void onConfigChanged() {
+            loadZenConfig();
+        }
+
+        @Override
         void onZenModeChanged() {
             final int mode = mZenModeHelper.getZenMode();
             if (mode == Global.ZEN_MODE_OFF) {
-                synchronized (mMutex) {
-                    if (mCurrentConditionId != null) {
-                        if (DEBUG) Slog.d(TAG, "Zen mode off, forcing unsubscribe from "
-                                + mCurrentConditionId);
-                        unsubscribeLocked(mCurrentConditionId);
-                        mCurrentConditionId = null;
-                    }
-                }
+                // ensure any manual condition is cleared
+                setZenModeCondition(null);
             }
         }
     }
+
+    private static class ConditionRecord {
+        public final Uri id;
+        public final ComponentName component;
+        public Condition condition;
+        public ManagedServiceInfo info;
+        public boolean isAutomatic;
+        public boolean isManual;
+
+        private ConditionRecord(Uri id, ComponentName component) {
+            this.id = id;
+            this.component = component;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("ConditionRecord[id=")
+                    .append(id).append(",component=").append(component);
+            if (isAutomatic) sb.append(",automatic");
+            if (isManual) sb.append(",manual");
+            return sb.append(']').toString();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 0621f58..d34b09c 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -101,7 +101,7 @@
 
     abstract protected IInterface asInterface(IBinder binder);
 
-    abstract protected void onServiceAdded(IInterface service);
+    abstract protected void onServiceAdded(ManagedServiceInfo info);
 
     protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
 
@@ -368,11 +368,12 @@
                             @Override
                             public void onServiceConnected(ComponentName name, IBinder binder) {
                                 boolean added = false;
+                                ManagedServiceInfo info = null;
                                 synchronized (mMutex) {
                                     mServicesBinding.remove(servicesBindingTag);
                                     try {
                                         mService = asInterface(binder);
-                                        ManagedServiceInfo info = newServiceInfo(mService, name,
+                                        info = newServiceInfo(mService, name,
                                                 userid, false /*isSystem*/, this, targetSdkVersion);
                                         binder.linkToDeath(info, 0);
                                         added = mServices.add(info);
@@ -381,7 +382,7 @@
                                     }
                                 }
                                 if (added) {
-                                    onServiceAdded(mService);
+                                    onServiceAdded(info);
                                 }
                             }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 76b4c89..7aa5d79 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1365,9 +1365,9 @@
         }
 
         @Override
-        public void requestZenModeConditions(IConditionListener callback, boolean requested) {
+        public void requestZenModeConditions(IConditionListener callback, int relevance) {
             enforceSystemOrSystemUI("INotificationManager.requestZenModeConditions");
-            mConditionProviders.requestZenModeConditions(callback, requested);
+            mConditionProviders.requestZenModeConditions(callback, relevance);
         }
 
         @Override
@@ -1376,6 +1376,18 @@
             mConditionProviders.setZenModeCondition(conditionId);
         }
 
+        @Override
+        public void setAutomaticZenModeConditions(Uri[] conditionIds) {
+            enforceSystemOrSystemUI("INotificationManager.setAutomaticZenModeConditions");
+            mConditionProviders.setAutomaticZenModeConditions(conditionIds);
+        }
+
+        @Override
+        public Condition[] getAutomaticZenModeConditions() {
+            enforceSystemOrSystemUI("INotificationManager.getAutomaticZenModeConditions");
+            return mConditionProviders.getAutomaticZenModeConditions();
+        }
+
         private void enforceSystemOrSystemUI(String message) {
             if (isCallerSystem()) return;
             getContext().enforceCallingPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
@@ -1610,7 +1622,8 @@
 
                 // Should this notification make noise, vibe, or use the LED?
                 final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD) && !intercept;
-                if (DBG) Slog.v(TAG, "canInterrupt=" + canInterrupt + " intercept=" + intercept);
+                if (DBG || intercept) Slog.v(TAG,
+                        "pkg=" + pkg + " canInterrupt=" + canInterrupt + " intercept=" + intercept);
                 synchronized (mNotificationList) {
                     final StatusBarNotification n = new StatusBarNotification(
                             pkg, opPkg, id, tag, callingUid, callingPid, score, notification,
@@ -2330,8 +2343,8 @@
         }
 
         @Override
-        public void onServiceAdded(IInterface service) {
-            final INotificationListener listener = (INotificationListener) service;
+        public void onServiceAdded(ManagedServiceInfo info) {
+            final INotificationListener listener = (INotificationListener) info.service;
             final String[] keys = getActiveNotificationKeysFromListener(listener);
             try {
                 listener.onListenerConnected(keys);
diff --git a/services/core/java/com/android/server/pm/ForwardingIntentFilter.java b/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
new file mode 100644
index 0000000..aba796b
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 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.pm;
+
+import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+import android.content.IntentFilter;
+import android.util.Log;
+import java.io.IOException;
+import android.os.UserHandle;
+
+/**
+ * The {@link PackageManagerService} maintains some {@link ForwardingIntentFilter}s for every user.
+ * If an {@link Intent} matches the {@link ForwardingIntentFilter}, then it can be forwarded to the
+ * {@link #mUserIdDest}.
+ */
+class ForwardingIntentFilter extends IntentFilter {
+    private static final String ATTR_USER_ID_DEST = "userIdDest";
+    private static final String ATTR_FILTER = "filter";
+
+    private static final String TAG = "ForwardingIntentFilter";
+
+    // If the intent matches the IntentFilter, then it can be forwarded to this userId.
+    final int mUserIdDest;
+
+    ForwardingIntentFilter(IntentFilter filter, int userIdDest) {
+        super(filter);
+        mUserIdDest = userIdDest;
+    }
+
+    public int getUserIdDest() {
+        return mUserIdDest;
+    }
+
+    ForwardingIntentFilter(XmlPullParser parser) throws XmlPullParserException, IOException {
+        String userIdDestString = parser.getAttributeValue(null, ATTR_USER_ID_DEST);
+        if (userIdDestString == null) {
+            String msg = "Missing element under " + TAG +": " + ATTR_USER_ID_DEST + " at " +
+                    parser.getPositionDescription();
+            PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+            mUserIdDest = UserHandle.USER_NULL;
+        } else {
+            mUserIdDest = Integer.parseInt(userIdDestString);
+        }
+        int outerDepth = parser.getDepth();
+        String tagName = parser.getName();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            tagName = parser.getName();
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            } else if (type == XmlPullParser.START_TAG) {
+                if (tagName.equals(ATTR_FILTER)) {
+                    break;
+                } else {
+                    String msg = "Unknown element under " + Settings.TAG_FORWARDING_INTENT_FILTERS
+                            + ": " + tagName + " at " + parser.getPositionDescription();
+                    PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+                    XmlUtils.skipCurrentTag(parser);
+                }
+            }
+        }
+        if (tagName.equals(ATTR_FILTER)) {
+            readFromXml(parser);
+        } else {
+            String msg = "Missing element under " + TAG + ": " + ATTR_FILTER +
+                    " at " + parser.getPositionDescription();
+            PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+            XmlUtils.skipCurrentTag(parser);
+        }
+    }
+
+    public void writeToXml(XmlSerializer serializer) throws IOException {
+        serializer.attribute(null, ATTR_USER_ID_DEST, Integer.toString(mUserIdDest));
+        serializer.startTag(null, ATTR_FILTER);
+            super.writeToXml(serializer);
+        serializer.endTag(null, ATTR_FILTER);
+    }
+
+    @Override
+    public String toString() {
+        return "ForwardingIntentFilter{0x" + Integer.toHexString(System.identityHashCode(this))
+                + " " + Integer.toString(mUserIdDest) + "}";
+    }
+}
diff --git a/services/core/java/com/android/server/pm/ForwardingIntentResolver.java b/services/core/java/com/android/server/pm/ForwardingIntentResolver.java
new file mode 100644
index 0000000..1616395
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ForwardingIntentResolver.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 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.pm;
+
+
+import java.io.PrintWriter;
+import com.android.server.IntentResolver;
+import java.util.List;
+
+/**
+ * Used to find a list of {@link ForwardingIntentFilter}s that match an intent.
+ */
+class ForwardingIntentResolver
+        extends IntentResolver<ForwardingIntentFilter, ForwardingIntentFilter> {
+    @Override
+    protected ForwardingIntentFilter[] newArray(int size) {
+        return new ForwardingIntentFilter[size];
+    }
+
+    @Override
+    protected boolean isPackageForFilter(String packageName, ForwardingIntentFilter filter) {
+        return false;
+    }
+
+    @Override
+    protected void sortResults(List<ForwardingIntentFilter> results) {
+        //We don't sort the results
+    }
+}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 6030d4d..48e9737 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -16,14 +16,18 @@
 
 package com.android.server.pm;
 
+import android.app.AppGlobals;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ILauncherApps;
 import android.content.pm.IOnAppsChangedListener;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.graphics.Rect;
@@ -34,6 +38,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.content.PackageMonitor;
@@ -46,7 +51,7 @@
  * managed profiles. 
  */
 public class LauncherAppsService extends ILauncherApps.Stub {
-
+    private static final boolean DEBUG = false;
     private static final String TAG = "LauncherAppsService";
     private final Context mContext;
     private final PackageManager mPm;
@@ -69,11 +74,17 @@
     @Override
     public void addOnAppsChangedListener(IOnAppsChangedListener listener) throws RemoteException {
         synchronized (mListeners) {
+            if (DEBUG) {
+                Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle());
+            }
             if (mListeners.getRegisteredCallbackCount() == 0) {
+                if (DEBUG) {
+                    Log.d(TAG, "Starting package monitoring");
+                }
                 startWatchingPackageBroadcasts();
             }
             mListeners.unregister(listener);
-            mListeners.register(listener);
+            mListeners.register(listener, Binder.getCallingUserHandle());
         }
     }
 
@@ -85,6 +96,9 @@
     public void removeOnAppsChangedListener(IOnAppsChangedListener listener)
             throws RemoteException {
         synchronized (mListeners) {
+            if (DEBUG) {
+                Log.d(TAG, "Removing listener from " + Binder.getCallingUserHandle());
+            }
             mListeners.unregister(listener);
             if (mListeners.getRegisteredCallbackCount() == 0) {
                 stopWatchingPackageBroadcasts();
@@ -103,11 +117,17 @@
      * Unregister package broadcast receiver
      */
     private void stopWatchingPackageBroadcasts() {
+        if (DEBUG) {
+            Log.d(TAG, "Stopped watching for packages");
+        }
         mPackageMonitor.unregister();
     }
 
     void checkCallbackCount() {
-        synchronized (LauncherAppsService.this) {
+        synchronized (mListeners) {
+            if (DEBUG) {
+                Log.d(TAG, "Callback count = " + mListeners.getRegisteredCallbackCount());
+            }
             if (mListeners.getRegisteredCallbackCount() == 0) {
                 stopWatchingPackageBroadcasts();
             }
@@ -170,6 +190,34 @@
     }
 
     @Override
+    public boolean isPackageEnabled(String packageName, UserHandle user)
+            throws RemoteException {
+        ensureInUserProfiles(user, "Cannot check package for unrelated profile " + user);
+        long ident = Binder.clearCallingIdentity();
+        try {
+            IPackageManager pm = AppGlobals.getPackageManager();
+            PackageInfo info = pm.getPackageInfo(packageName, 0, user.getIdentifier());
+            return info != null && info.applicationInfo.enabled;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
+    public boolean isActivityEnabled(ComponentName component, UserHandle user)
+            throws RemoteException {
+        ensureInUserProfiles(user, "Cannot check component for unrelated profile " + user);
+        long ident = Binder.clearCallingIdentity();
+        try {
+            IPackageManager pm = AppGlobals.getPackageManager();
+            ActivityInfo info = pm.getActivityInfo(component, 0, user.getIdentifier());
+            return info != null && info.isEnabled();
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
     public void startActivityAsUser(ComponentName component, Rect sourceBounds,
             Bundle opts, UserHandle user) throws RemoteException {
         ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
@@ -191,13 +239,44 @@
 
     private class MyPackageMonitor extends PackageMonitor {
 
+        /** Checks if user is a profile of or same as listeningUser. */
+        private boolean isProfileOf(UserHandle user, UserHandle listeningUser, String debugMsg) {
+            if (user.getIdentifier() == listeningUser.getIdentifier()) {
+                if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg);
+                return true;
+            }
+            long ident = Binder.clearCallingIdentity();
+            try {
+                UserInfo userInfo = mUm.getUserInfo(user.getIdentifier());
+                UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier());
+                if (userInfo == null || listeningUserInfo == null
+                        || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
+                        || userInfo.profileGroupId != listeningUserInfo.profileGroupId) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Not delivering msg from " + user + " to " + listeningUser + ":"
+                                + debugMsg);
+                    }
+                    return false;
+                } else {
+                    if (DEBUG) {
+                        Log.d(TAG, "Delivering msg from " + user + " to " + listeningUser + ":"
+                                + debugMsg);
+                    }
+                    return true;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         @Override
         public void onPackageAdded(String packageName, int uid) {
             UserHandle user = new UserHandle(getChangingUserId());
-            // TODO: if (!isProfile(user)) return;
             final int n = mListeners.beginBroadcast();
             for (int i = 0; i < n; i++) {
                 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
+                if (!isProfileOf(user, listeningUser, "onPackageAdded")) continue;
                 try {
                     listener.onPackageAdded(user, packageName);
                 } catch (RemoteException re) {
@@ -212,10 +291,11 @@
         @Override
         public void onPackageRemoved(String packageName, int uid) {
             UserHandle user = new UserHandle(getChangingUserId());
-            // TODO: if (!isCurrentProfile(user)) return;
             final int n = mListeners.beginBroadcast();
             for (int i = 0; i < n; i++) {
                 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
+                if (!isProfileOf(user, listeningUser, "onPackageRemoved")) continue;
                 try {
                     listener.onPackageRemoved(user, packageName);
                 } catch (RemoteException re) {
@@ -230,10 +310,11 @@
         @Override
         public void onPackageModified(String packageName) {
             UserHandle user = new UserHandle(getChangingUserId());
-            // TODO: if (!isProfile(user)) return;
             final int n = mListeners.beginBroadcast();
             for (int i = 0; i < n; i++) {
                 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
+                if (!isProfileOf(user, listeningUser, "onPackageModified")) continue;
                 try {
                     listener.onPackageChanged(user, packageName);
                 } catch (RemoteException re) {
@@ -248,10 +329,11 @@
         @Override
         public void onPackagesAvailable(String[] packages) {
             UserHandle user = new UserHandle(getChangingUserId());
-            // TODO: if (!isProfile(user)) return;
             final int n = mListeners.beginBroadcast();
             for (int i = 0; i < n; i++) {
                 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
+                if (!isProfileOf(user, listeningUser, "onPackagesAvailable")) continue;
                 try {
                     listener.onPackagesAvailable(user, packages, isReplacing());
                 } catch (RemoteException re) {
@@ -266,10 +348,11 @@
         @Override
         public void onPackagesUnavailable(String[] packages) {
             UserHandle user = new UserHandle(getChangingUserId());
-            // TODO: if (!isProfile(user)) return;
             final int n = mListeners.beginBroadcast();
             for (int i = 0; i < n; i++) {
                 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
+                if (!isProfileOf(user, listeningUser, "onPackagesUnavailable")) continue;
                 try {
                     listener.onPackagesUnavailable(user, packages, isReplacing());
                 } catch (RemoteException re) {
@@ -284,7 +367,6 @@
     }
 
     class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> {
-
         @Override
         public void onCallbackDied(T callback, Object cookie) {
             checkCallbackCount();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 038e2dd..a133d42 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -28,6 +28,8 @@
 import static android.system.OsConstants.S_IXGRP;
 import static android.system.OsConstants.S_IROTH;
 import static android.system.OsConstants.S_IXOTH;
+import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER;
+import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.util.ArrayUtils.appendInt;
 import static com.android.internal.util.ArrayUtils.removeInt;
 
@@ -3162,6 +3164,33 @@
         return null;
     }
 
+    /*
+     * Returns if intent can be forwarded from the userId from to dest
+     */
+    @Override
+    public boolean canForwardTo(Intent intent, String resolvedType, int userIdFrom, int userIdDest) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+        List<ForwardingIntentFilter> matches =
+                getMatchingForwardingIntentFilters(intent, resolvedType, userIdFrom);
+        if (matches != null) {
+            int size = matches.size();
+            for (int i = 0; i < size; i++) {
+                if (matches.get(i).getUserIdDest() == userIdDest) return true;
+            }
+        }
+        return false;
+    }
+
+    private List<ForwardingIntentFilter> getMatchingForwardingIntentFilters(Intent intent,
+            String resolvedType, int userId) {
+        ForwardingIntentResolver fir = mSettings.mForwardingIntentResolvers.get(userId);
+        if (fir != null) {
+            return fir.queryIntent(intent, resolvedType, false, userId);
+        }
+        return null;
+    }
+
     @Override
     public List<ResolveInfo> queryIntentActivities(Intent intent,
             String resolvedType, int flags, int userId) {
@@ -3190,7 +3219,38 @@
         synchronized (mPackages) {
             final String pkgName = intent.getPackage();
             if (pkgName == null) {
-                return mActivities.queryIntent(intent, resolvedType, flags, userId);
+                List<ResolveInfo> result =
+                        mActivities.queryIntent(intent, resolvedType, flags, userId);
+                // Checking if we can forward the intent to another user
+                List<ForwardingIntentFilter> fifs =
+                        getMatchingForwardingIntentFilters(intent, resolvedType, userId);
+                if (fifs != null) {
+                    ForwardingIntentFilter forwardingIntentFilterWithResult = null;
+                    HashSet<Integer> alreadyTriedUserIds = new HashSet<Integer>();
+                    for (ForwardingIntentFilter fif : fifs) {
+                        int userIdDest = fif.getUserIdDest();
+                        // Two {@link ForwardingIntentFilter}s can have the same userIdDest and
+                        // match the same an intent. For performance reasons, it is better not to
+                        // run queryIntent twice for the same userId
+                        if (!alreadyTriedUserIds.contains(userIdDest)) {
+                            List<ResolveInfo> resultUser = mActivities.queryIntent(intent,
+                                    resolvedType, flags, userIdDest);
+                            if (resultUser != null) {
+                                forwardingIntentFilterWithResult = fif;
+                                // As soon as there is a match in another user, we add the
+                                // intentForwarderActivity to the list of ResolveInfo.
+                                break;
+                            }
+                            alreadyTriedUserIds.add(userIdDest);
+                        }
+                    }
+                    if (forwardingIntentFilterWithResult != null) {
+                        ResolveInfo forwardingResolveInfo = createForwardingResolveInfo(
+                                forwardingIntentFilterWithResult, userId);
+                        result.add(forwardingResolveInfo);
+                    }
+                }
+                return result;
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
@@ -3201,6 +3261,28 @@
         }
     }
 
+    private ResolveInfo createForwardingResolveInfo(ForwardingIntentFilter fif, int userIdFrom) {
+        String className;
+        int userIdDest = fif.getUserIdDest();
+        if (userIdDest == UserHandle.USER_OWNER) {
+            className = FORWARD_INTENT_TO_USER_OWNER;
+        } else {
+            className = FORWARD_INTENT_TO_MANAGED_PROFILE;
+        }
+        ComponentName forwardingActivityComponentName = new ComponentName(
+                mAndroidApplication.packageName, className);
+        ActivityInfo forwardingActivityInfo = getActivityInfo(forwardingActivityComponentName, 0,
+                userIdFrom);
+        ResolveInfo forwardingResolveInfo = new ResolveInfo();
+        forwardingResolveInfo.activityInfo = forwardingActivityInfo;
+        forwardingResolveInfo.priority = 0;
+        forwardingResolveInfo.preferredOrder = 0;
+        forwardingResolveInfo.match = 0;
+        forwardingResolveInfo.isDefault = true;
+        forwardingResolveInfo.filter = fif;
+        return forwardingResolveInfo;
+    }
+
     @Override
     public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
             Intent[] specifics, String[] specificTypes, Intent intent,
@@ -5633,12 +5715,13 @@
             for (PackageSetting ps : packagesForUser) {
                 if (ps.requiredCpuAbiString == null) {
                     ps.requiredCpuAbiString = requirer.requiredCpuAbiString;
-                    ps.pkg.applicationInfo.requiredCpuAbi = requirer.requiredCpuAbiString;
-
-                    Slog.i(TAG, "Adjusting ABI for : " + ps.pkg.packageName + " to " + ps.requiredCpuAbiString);
-                    if (doDexOpt) {
-                        performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true);
-                        mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet());
+                    if (ps.pkg != null) {
+                        ps.pkg.applicationInfo.requiredCpuAbi = requirer.requiredCpuAbiString;
+                        Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + ps.requiredCpuAbiString);
+                        if (doDexOpt) {
+                            performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true);
+                            mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet());
+                        }
                     }
                 }
             }
@@ -11029,6 +11112,47 @@
         }
     }
 
+    /*
+     * For filters that are added with this method:
+     * if an intent for the user whose id is userIdOrig matches the filter, then this intent can
+     * also be resolved in the user whose id is userIdDest.
+     */
+    @Override
+    public void addForwardingIntentFilter(IntentFilter filter, int userIdOrig, int userIdDest) {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                    "addForwardingIntentFilter can only be run by the system");
+        }
+        if (filter.countActions() == 0) {
+            Slog.w(TAG, "Cannot set a forwarding intent filter with no filter actions");
+            return;
+        }
+        synchronized (mPackages) {
+            mSettings.editForwardingIntentResolverLPw(userIdOrig).addFilter(
+                    new ForwardingIntentFilter(filter, userIdDest));
+            mSettings.writePackageRestrictionsLPr(userIdOrig);
+        }
+    }
+
+    @Override
+    public void clearForwardingIntentFilters(int userIdOrig) {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                    "clearForwardingIntentFilter can only be run by the system");
+        }
+        synchronized (mPackages) {
+            ForwardingIntentResolver fir = mSettings.editForwardingIntentResolverLPw(userIdOrig);
+            HashSet<ForwardingIntentFilter> set =
+                    new HashSet<ForwardingIntentFilter>(fir.filterSet());
+            for (ForwardingIntentFilter fif : set) {
+                fir.removeFilter(fif);
+            }
+            mSettings.writePackageRestrictionsLPr(userIdOrig);
+        }
+    }
+
     @Override
     public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
         Intent intent = new Intent(Intent.ACTION_MAIN);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 678fc92..599d2a7 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -131,6 +131,8 @@
     private static final String TAG_PACKAGE = "pkg";
     private static final String TAG_PERSISTENT_PREFERRED_ACTIVITIES =
             "persistent-preferred-activities";
+    static final String TAG_FORWARDING_INTENT_FILTERS =
+            "forwarding-intent-filters";
 
     private static final String ATTR_NAME = "name";
     private static final String ATTR_USER = "user";
@@ -185,6 +187,10 @@
     final SparseArray<PersistentPreferredIntentResolver> mPersistentPreferredActivities =
             new SparseArray<PersistentPreferredIntentResolver>();
 
+    // For every user, it is used to find to which other users the intent can be forwarded.
+    final SparseArray<ForwardingIntentResolver> mForwardingIntentResolvers =
+            new SparseArray<ForwardingIntentResolver>();
+
     final HashMap<String, SharedUserSetting> mSharedUsers =
             new HashMap<String, SharedUserSetting>();
     private final ArrayList<Object> mUserIds = new ArrayList<Object>();
@@ -837,6 +843,15 @@
         return ppir;
     }
 
+    ForwardingIntentResolver editForwardingIntentResolverLPw(int userId) {
+        ForwardingIntentResolver fir = mForwardingIntentResolvers.get(userId);
+        if (fir == null) {
+            fir = new ForwardingIntentResolver();
+            mForwardingIntentResolvers.put(userId, fir);
+        }
+        return fir;
+    }
+
     private File getUserPackagesStateFile(int userId) {
         return new File(Environment.getUserSystemDirectory(userId), "package-restrictions.xml");
     }
@@ -952,6 +967,28 @@
         }
     }
 
+    private void readForwardingIntentFiltersLPw(XmlPullParser parser, int userId)
+            throws XmlPullParserException, IOException {
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            String tagName = parser.getName();
+            if (tagName.equals(TAG_ITEM)) {
+                ForwardingIntentFilter fif = new ForwardingIntentFilter(parser);
+                editForwardingIntentResolverLPw(userId).addFilter(fif);
+            } else {
+                String msg = "Unknown element under " +  TAG_FORWARDING_INTENT_FILTERS + ": " +
+                        parser.getName();
+                PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
     void readPackageRestrictionsLPr(int userId) {
         if (DEBUG_MU) {
             Log.i(TAG, "Reading package restrictions for user=" + userId);
@@ -1080,6 +1117,8 @@
                     readPreferredActivitiesLPw(parser, userId);
                 } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
                     readPersistentPreferredActivitiesLPw(parser, userId);
+                } else if (tagName.equals(TAG_FORWARDING_INTENT_FILTERS)) {
+                    readForwardingIntentFiltersLPw(parser, userId);
                 } else {
                     Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
                           + parser.getName());
@@ -1157,6 +1196,20 @@
         serializer.endTag(null, TAG_PERSISTENT_PREFERRED_ACTIVITIES);
     }
 
+    void writeForwardingIntentFiltersLPr(XmlSerializer serializer, int userId)
+            throws IllegalArgumentException, IllegalStateException, IOException {
+        serializer.startTag(null, TAG_FORWARDING_INTENT_FILTERS);
+        ForwardingIntentResolver fir = mForwardingIntentResolvers.get(userId);
+        if (fir != null) {
+            for (final ForwardingIntentFilter fif : fir.filterSet()) {
+                serializer.startTag(null, TAG_ITEM);
+                fif.writeToXml(serializer);
+                serializer.endTag(null, TAG_ITEM);
+            }
+        }
+        serializer.endTag(null, TAG_FORWARDING_INTENT_FILTERS);
+    }
+
     void writePackageRestrictionsLPr(int userId) {
         if (DEBUG_MU) {
             Log.i(TAG, "Writing package restrictions for user=" + userId);
@@ -1255,6 +1308,8 @@
 
             writePersistentPreferredActivitiesLPr(serializer, userId);
 
+            writeForwardingIntentFiltersLPr(serializer, userId);
+
             serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
 
             serializer.endDocument();
@@ -1872,6 +1927,10 @@
                     // TODO: check whether this is okay! as it is very
                     // similar to how preferred-activities are treated
                     readPersistentPreferredActivitiesLPw(parser, 0);
+                } else if (tagName.equals(TAG_FORWARDING_INTENT_FILTERS)) {
+                    // TODO: check whether this is okay! as it is very
+                    // similar to how preferred-activities are treated
+                    readForwardingIntentFiltersLPw(parser, 0);
                 } else if (tagName.equals("updated-package")) {
                     readDisabledSysPackageLPw(parser);
                 } else if (tagName.equals("cleaning-package")) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index f8103de..3239b46 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -23,7 +23,6 @@
 import android.app.ActivityManagerNative;
 import android.app.ActivityThread;
 import android.app.IStopUserCallback;
-import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -274,16 +273,6 @@
 
     /** Assume permissions already checked and caller's identity cleared */
     private List<UserInfo> getProfilesLocked(int userId, boolean enabledOnly) {
-        // Getting the service here is not good for testing purposes.
-        // However, this service is not available when UserManagerService starts
-        // up so we need a lazy load.
-
-        DevicePolicyManager dpm = null;
-        if (enabledOnly) {
-            dpm = (DevicePolicyManager)
-                    mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
-        }
-
         UserInfo user = getUserInfoLocked(userId);
         ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
         for (int i = 0; i < mUsers.size(); i++) {
@@ -291,23 +280,8 @@
             if (!isProfileOf(user, profile)) {
                 continue;
             }
-
-            if (enabledOnly && profile.isManagedProfile()) {
-                if (dpm != null) {
-                    if (!dpm.isProfileEnabled(profile.id)) {
-                        continue;
-                    }
-                } else {
-                    Log.w(LOG_TAG,
-                            "Attempting to reach DevicePolicyManager before it is started");
-                    // TODO: There might be system apps that need to call this.
-                    // Make sure that DevicePolicyManagerService is ready at that
-                    // time (otherwise, any default value is a bad one).
-                    throw new IllegalArgumentException(String.format(
-                            "Attempting to get enabled profiles for %d before "
-                                    + "DevicePolicyManagerService has been started.",
-                            userId));
-                }
+            if (enabledOnly && !profile.isEnabled()) {
+                continue;
             }
             users.add(profile);
         }
@@ -321,6 +295,18 @@
     }
 
     @Override
+    public void setUserEnabled(int userId) {
+        checkManageUsersPermission("enable user");
+        synchronized (mPackagesLock) {
+            UserInfo info = getUserInfoLocked(userId);
+            if (info != null && !info.isEnabled()) {
+                info.flags ^= UserInfo.FLAG_DISABLED;
+                writeUserLocked(info);
+            }
+        }
+    }
+
+    @Override
     public UserInfo getUserInfo(int userId) {
         checkManageUsersPermission("query user");
         synchronized (mPackagesLock) {
@@ -1106,6 +1092,9 @@
             // on next startup, in case the runtime stops now before stopping and
             // removing the user completely.
             user.partial = true;
+            // Mark it as disabled, so that it isn't returned any more when
+            // profiles are queried.
+            user.flags |= UserInfo.FLAG_DISABLED;
             writeUserLocked(user);
         }
         if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
@@ -1134,6 +1123,7 @@
         // wiping the user's system directory and removing from the user list
         long ident = Binder.clearCallingIdentity();
         try {
+            final boolean isManaged = getUserInfo(userHandle).isManagedProfile();
             Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
             addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
             mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
@@ -1154,6 +1144,11 @@
                                             removeUserStateLocked(userHandle);
                                         }
                                     }
+                                    // Send broadcast to notify system that the user removed was a
+                                    // managed user.
+                                    if (isManaged) {
+                                        sendProfileRemovedBroadcast(userHandle);
+                                    }
                                 }
                             }.start();
                         }
@@ -1205,6 +1200,13 @@
         parent.delete();
     }
 
+    private void sendProfileRemovedBroadcast(int userHandle) {
+        Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+        managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(userHandle));
+        // Note: This makes an assumption that the parent owner is user 0.
+        mContext.sendBroadcastAsUser(managedProfileIntent, UserHandle.OWNER, null);
+    }
+
     @Override
     public Bundle getApplicationRestrictions(String packageName) {
         return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index d84e8e1..d9e95c7 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -409,7 +409,7 @@
 
         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
 
-        mPolicy.screenTurningOn(mScreenOnListener);
+        mPolicy.wakingUp(mScreenOnListener);
         mActivityManagerInternal.wakingUp();
 
         if (ActivityManagerNative.isSystemReady()) {
@@ -460,7 +460,7 @@
 
         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
 
-        mPolicy.screenTurnedOff(why);
+        mPolicy.goingToSleep(why);
         mActivityManagerInternal.goingToSleep();
 
         if (ActivityManagerNative.isSystemReady()) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index cfe24fe..6d2e8592 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -496,6 +496,7 @@
 
             filter = new IntentFilter();
             filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+            filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
             mContext.registerReceiver(new BootCompletedReceiver(), filter, null, mHandler);
 
             filter = new IntentFilter();
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index 486477a..5deb2b8 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -70,8 +70,9 @@
      */
     public SearchManagerService(Context context)  {
         mContext = context;
-        mContext.registerReceiver(new BootCompletedReceiver(),
-                new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+        IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiver(new BootCompletedReceiver(), filter);
         mContext.registerReceiver(new UserReceiver(),
                 new IntentFilter(Intent.ACTION_USER_REMOVED));
         new MyPackageMonitor().register(context, null, UserHandle.ALL, true);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index a2a49c9..9061f96 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -187,7 +187,7 @@
 
         boolean trustMayHaveChanged = false;
         for (int i = 0; i < mObsoleteAgents.size(); i++) {
-            AgentInfo info = mActiveAgents.valueAt(i);
+            AgentInfo info = mObsoleteAgents.valueAt(i);
             if (info.agent.isTrusted()) {
                 trustMayHaveChanged = true;
             }
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index f3e8f3c..527216d 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -19,57 +19,173 @@
 #define LOG_NDEBUG 1
 
 #include "JNIHelp.h"
+#include "ScopedPrimitiveArray.h"
+
+#include <string>
 
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
 #include <hardware/hdmi_cec.h>
+#include <sys/param.h>
 
 namespace android {
 
 static struct {
-    jmethodID handleMessage;
+    jmethodID handleIncomingCecCommand;
+    jmethodID handleHotplug;
 } gHdmiCecControllerClassInfo;
 
-
 class HdmiCecController {
 public:
-    HdmiCecController(jobject callbacksObj);
+    HdmiCecController(hdmi_cec_device_t* device, jobject callbacksObj);
+
+    void init();
+
+    // Send message to other device. Note that it runs in IO thread.
+    int sendMessage(const cec_message_t& message);
 
 private:
-    static void onReceived(const hdmi_event_t* event, void* arg);
+    // Propagate the message up to Java layer.
+    void propagateCecCommand(const cec_message_t& message);
+    void propagateHotplugEvent(const hotplug_event_t& event);
 
+    static void onReceived(const hdmi_event_t* event, void* arg);
+    static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
+
+    hdmi_cec_device_t* mDevice;
     jobject mCallbacksObj;
 };
 
-HdmiCecController::HdmiCecController(jobject callbacksObj) :
+HdmiCecController::HdmiCecController(hdmi_cec_device_t* device, jobject callbacksObj) :
+    mDevice(device),
     mCallbacksObj(callbacksObj) {
 }
 
+void HdmiCecController::init() {
+    mDevice->register_event_callback(mDevice, HdmiCecController::onReceived, this);
+}
+
+void HdmiCecController::propagateCecCommand(const cec_message_t& message) {
+    jint srcAddr = message.initiator;
+    jint dstAddr = message.destination;
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jbyteArray body = env->NewByteArray(message.length);
+    const jbyte* bodyPtr = reinterpret_cast<const jbyte *>(message.body);
+    env->SetByteArrayRegion(body, 0, message.length, bodyPtr);
+
+    env->CallVoidMethod(mCallbacksObj,
+            gHdmiCecControllerClassInfo.handleIncomingCecCommand,
+            srcAddr, dstAddr, body);
+    env->DeleteLocalRef(body);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
+void HdmiCecController::propagateHotplugEvent(const hotplug_event_t& event) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj,
+            gHdmiCecControllerClassInfo.handleHotplug, event.connected);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
+int HdmiCecController::sendMessage(const cec_message_t& message) {
+    // TODO: propagate send_message's return value.
+    return mDevice->send_message(mDevice, &message);
+}
+
+// static
+void HdmiCecController::checkAndClearExceptionFromCallback(JNIEnv* env,
+        const char* methodName) {
+    if (env->ExceptionCheck()) {
+        ALOGE("An exception was thrown by callback '%s'.", methodName);
+        LOGE_EX(env);
+        env->ExceptionClear();
+    }
+}
+
 // static
 void HdmiCecController::onReceived(const hdmi_event_t* event, void* arg) {
-    HdmiCecController* handler = static_cast<HdmiCecController*>(arg);
-    if (handler == NULL) {
+    HdmiCecController* controller = static_cast<HdmiCecController*>(arg);
+    if (controller == NULL) {
         return;
     }
 
-    // TODO: propagate message to Java layer.
+    switch (event->type) {
+    case HDMI_EVENT_CEC_MESSAGE:
+        controller->propagateCecCommand(event->cec);
+        break;
+    case HDMI_EVENT_HOT_PLUG:
+        controller->propagateHotplugEvent(event->hotplug);
+        break;
+    default:
+        ALOGE("Unsupported event type: %d", event->type);
+        break;
+    }
 }
 
-
 //------------------------------------------------------------------------------
+#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find method " methodName);
+
 static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj) {
-    // TODO: initialize hal and pass it to controller if ready.
+    int err;
+    // If use same hardware module id between HdmiCecService and
+    // HdmiControlSservice it may conflict and cause abnormal state of HAL.
+    // TODO: use HDMI_CEC_HARDWARE_MODULE_ID of hdmi_cec.h for module id
+    //       once migration to HdmiControlService is done.
+    hw_module_t* module;
+    err = hw_get_module("hdmi_cec_module",
+            const_cast<const hw_module_t **>(&module));
+    if (err != 0) {
+        ALOGE("Error acquiring hardware module: %d", err);
+        return 0;
+    }
+    hw_device_t* device;
+    // TODO: use HDMI_CEC_HARDWARE_INTERFACE of hdmi_cec.h for interface name
+    //       once migration to HdmiControlService is done.
+    err = module->methods->open(module, "hdmi_cec_module_hw_if", &device);
+    if (err != 0) {
+        ALOGE("Error opening hardware module: %d", err);
+        return 0;
+    }
 
     HdmiCecController* controller = new HdmiCecController(
+            reinterpret_cast<hdmi_cec_device*>(device),
             env->NewGlobalRef(callbacksObj));
+    controller->init();
+
+    GET_METHOD_ID(gHdmiCecControllerClassInfo.handleIncomingCecCommand, clazz,
+            "handleIncomingCecCommand", "(II[B)V");
+    GET_METHOD_ID(gHdmiCecControllerClassInfo.handleHotplug, clazz,
+            "handleHotplug", "(Z)V");
 
     return reinterpret_cast<jlong>(controller);
 }
 
+static jint nativeSendCecCommand(JNIEnv* env, jclass clazz, jlong controllerPtr,
+        jint srcAddr, jint dstAddr, jbyteArray body) {
+    cec_message_t message;
+    message.initiator = static_cast<cec_logical_address_t>(srcAddr);
+    message.destination = static_cast<cec_logical_address_t>(dstAddr);
+
+    jsize len = env->GetArrayLength(body);
+    message.length = MIN(len, CEC_MESSAGE_BODY_MAX_LENGTH);
+    ScopedByteArrayRO bodyPtr(env, body);
+    std::memcpy(message.body, bodyPtr.get(), len);
+
+    HdmiCecController* controller =
+            reinterpret_cast<HdmiCecController*>(controllerPtr);
+    return controller->sendMessage(message);
+}
+
 static JNINativeMethod sMethods[] = {
     /* name, signature, funcPtr */
     { "nativeInit", "(Lcom/android/server/hdmi/HdmiCecController;)J",
             (void *) nativeInit },
+    { "nativeSendCecCommand", "(JII[B)I",
+            (void *) nativeSendCecCommand },
 };
 
 #define CLASS_PATH "com/android/server/hdmi/HdmiCecController"
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index 3c46e40..1647425 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -53,7 +53,6 @@
     private static final String ATTR_NAME = "name";
     private static final String ATTR_PACKAGE = "package";
     private static final String ATTR_USERID = "userId";
-    private static final String ATTR_ENABLED = "profileEnabled";
 
     private AtomicFile fileForWriting;
 
@@ -104,8 +103,7 @@
      */
     static DeviceOwner createWithProfileOwner(String packageName, String ownerName, int userId) {
         DeviceOwner owner = new DeviceOwner();
-        owner.mProfileOwners.put(
-                userId, new OwnerInfo(ownerName, packageName, false /* disabled */));
+        owner.mProfileOwners.put(userId, new OwnerInfo(ownerName, packageName));
         return owner;
     }
 
@@ -122,7 +120,7 @@
     }
 
     void setProfileOwner(String packageName, String ownerName, int userId) {
-        mProfileOwners.put(userId, new OwnerInfo(ownerName, packageName, false /* disabled */));
+        mProfileOwners.put(userId, new OwnerInfo(ownerName, packageName));
     }
 
     void removeProfileOwner(int userId) {
@@ -139,19 +137,6 @@
         return profileOwner != null ? profileOwner.name : null;
     }
 
-    boolean isProfileEnabled(int userId) {
-        OwnerInfo profileOwner = mProfileOwners.get(userId);
-        return profileOwner != null ? profileOwner.enabled : true;
-    }
-
-    void setProfileEnabled(int userId) {
-        OwnerInfo profileOwner = mProfileOwners.get(userId);
-        if (profileOwner == null) {
-            throw new IllegalArgumentException("No profile owner exists.");
-        }
-        profileOwner.enabled = true;
-    }
-
     boolean hasDeviceOwner() {
         return mDeviceOwner != null;
     }
@@ -203,12 +188,9 @@
                 } else if (tag.equals(TAG_PROFILE_OWNER)) {
                     String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
                     String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME);
-                    Boolean profileEnabled = Boolean.parseBoolean(
-                            parser.getAttributeValue(null, ATTR_ENABLED));
                     int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID));
                     mProfileOwners.put(userId,
-                            new OwnerInfo(
-                                    profileOwnerName, profileOwnerPackageName, profileEnabled));
+                            new OwnerInfo(profileOwnerName, profileOwnerPackageName));
                 } else {
                     throw new XmlPullParserException(
                             "Unexpected tag in device owner file: " + tag);
@@ -251,7 +233,6 @@
                     out.startTag(null, TAG_PROFILE_OWNER);
                     out.attribute(null, ATTR_PACKAGE, owner.getValue().packageName);
                     out.attribute(null, ATTR_NAME, owner.getValue().name);
-                    out.attribute(null, ATTR_ENABLED, String.valueOf(owner.getValue().enabled));
                     out.attribute(null, ATTR_USERID, Integer.toString(owner.getKey()));
                     out.endTag(null, TAG_PROFILE_OWNER);
                 }
@@ -292,12 +273,6 @@
     static class OwnerInfo {
         public String name;
         public String packageName;
-        public boolean enabled = true; // only makes sense for managed profiles
-
-        public OwnerInfo(String name, String packageName, boolean enabled) {
-            this(name, packageName);
-            this.enabled = enabled;
-        }
 
         public OwnerInfo(String name, String packageName) {
             this.name = name;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f1ee280..d0a6db1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -588,6 +588,7 @@
         filter.addAction(Intent.ACTION_USER_REMOVED);
         filter.addAction(Intent.ACTION_USER_STARTED);
         filter.addAction(KeyChain.ACTION_STORAGE_CHANGED);
+        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
         filter = new IntentFilter();
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
@@ -2903,11 +2904,10 @@
             int userId = UserHandle.getCallingUserId();
             Slog.d(LOG_TAG, "Enabling the profile for: " + userId);
 
-            mDeviceOwner.setProfileEnabled(userId);
-            mDeviceOwner.writeOwnerFile();
-
+            UserManager um = UserManager.get(mContext);
             long id = Binder.clearCallingIdentity();
             try {
+                um.setUserEnabled(userId);
                 Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
                 intent.putExtra(Intent.EXTRA_USER, new UserHandle(UserHandle.getCallingUserId()));
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
@@ -2948,23 +2948,6 @@
         return null;
     }
 
-    @Override
-    public boolean isProfileEnabled(int userHandle) {
-        if (!mHasFeature) {
-            // If device policy management is not enabled, then the userHandle cannot belong to a
-            // managed profile. All other profiles are considered enabled.
-            return true;
-        }
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-
-        synchronized (this) {
-            if (mDeviceOwner != null) {
-                 return mDeviceOwner.isProfileEnabled(userHandle);
-            }
-        }
-        return true;
-    }
-
     private boolean isDeviceProvisioned() {
         return Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.DEVICE_PROVISIONED, 0) > 0;
@@ -3099,6 +3082,51 @@
         }
     }
 
+    public void forwardMatchingIntents(ComponentName who, IntentFilter filter, int flags) {
+        int callingUserId = UserHandle.getCallingUserId();
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            IPackageManager pm = AppGlobals.getPackageManager();
+            long id = Binder.clearCallingIdentity();
+            try {
+                if ((flags & DevicePolicyManager.FLAG_TO_PRIMARY_USER) != 0) {
+                    pm.addForwardingIntentFilter(filter, callingUserId, UserHandle.USER_OWNER);
+                }
+                if ((flags & DevicePolicyManager.FLAG_TO_MANAGED_PROFILE) != 0) {
+                    pm.addForwardingIntentFilter(filter, UserHandle.USER_OWNER, callingUserId);
+                }
+            } catch (RemoteException re) {
+                // Shouldn't happen
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
+
+    public void clearForwardingIntentFilters(ComponentName who) {
+        int callingUserId = UserHandle.getCallingUserId();
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            IPackageManager pm = AppGlobals.getPackageManager();
+            long id = Binder.clearCallingIdentity();
+            try {
+                pm.clearForwardingIntentFilters(callingUserId);
+                pm.clearForwardingIntentFilters(UserHandle.USER_OWNER);
+            } catch (RemoteException re) {
+                // Shouldn't happen
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
+
     @Override
     public Bundle getApplicationRestrictions(ComponentName who, String packageName) {
         final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3d82027..7c9f7a8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -923,7 +923,6 @@
             }
 
             try {
-                Slog.i(TAG, "MediaSessionService");
                 mSystemServiceManager.startService(MediaSessionService.class);
             } catch (Throwable e) {
                 reportWtf("starting MediaSessionService", e);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index f5ac178..6822ee3 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -373,8 +373,9 @@
                 mUEventObserver.startObserving(USB_STATE_MATCH);
                 mUEventObserver.startObserving(ACCESSORY_START_MATCH);
 
-                mContext.registerReceiver(
-                        mBootCompletedReceiver, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+                IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+                filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+                mContext.registerReceiver(mBootCompletedReceiver, filter);
                 mContext.registerReceiver(
                         mUserSwitchedReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
             } catch (Exception e) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 045c0f6..16afc8f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -28,6 +28,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.voice.IVoiceInteractionService;
@@ -88,6 +90,21 @@
         private boolean mSafeMode;
         private int mCurUser;
 
+        @Override
+        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                throws RemoteException {
+            try {
+                return super.onTransact(code, data, reply, flags);
+            } catch (RuntimeException e) {
+                // The activity manager only throws security exceptions, so let's
+                // log all others.
+                if (!(e instanceof SecurityException)) {
+                    Slog.wtf(TAG, "VoiceInteractionManagerService Crash", e);
+                }
+                throw e;
+            }
+        }
+
         public void systemRunning(boolean safeMode) {
             mSafeMode = safeMode;
 
@@ -97,18 +114,18 @@
 
             synchronized (this) {
                 mCurUser = ActivityManager.getCurrentUser();
-                switchImplementationIfNeededLocked();
+                switchImplementationIfNeededLocked(false);
             }
         }
 
         public void switchUser(int userHandle) {
             synchronized (this) {
                 mCurUser = userHandle;
-                switchImplementationIfNeededLocked();
+                switchImplementationIfNeededLocked(false);
             }
         }
 
-        void switchImplementationIfNeededLocked() {
+        void switchImplementationIfNeededLocked(boolean force) {
             if (!mSafeMode) {
                 String curService = Settings.Secure.getStringForUser(
                         mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
@@ -121,7 +138,7 @@
                         serviceComponent = null;
                     }
                 }
-                if (mImpl == null || mImpl.mUser != mCurUser
+                if (force || mImpl == null || mImpl.mUser != mCurUser
                         || !mImpl.mComponent.equals(serviceComponent)) {
                     if (mImpl != null) {
                         mImpl.shutdownLocked();
@@ -138,10 +155,10 @@
         }
 
         @Override
-        public void startVoiceActivity(Intent intent, String resolvedType,
-                IVoiceInteractionService service, Bundle args) {
+        public void startSession(IVoiceInteractionService service, Bundle args) {
             synchronized (this) {
-                if (mImpl == null || service.asBinder() != mImpl.mService.asBinder()) {
+                if (mImpl == null || mImpl.mService == null
+                        || service.asBinder() != mImpl.mService.asBinder()) {
                     throw new SecurityException(
                             "Caller is not the current voice interaction service");
                 }
@@ -149,8 +166,7 @@
                 final int callingUid = Binder.getCallingUid();
                 final long caller = Binder.clearCallingIdentity();
                 try {
-                    mImpl.startVoiceActivityLocked(callingPid, callingUid,
-                            intent, resolvedType, args);
+                    mImpl.startSessionLocked(callingPid, callingUid, args);
                 } finally {
                     Binder.restoreCallingIdentity(caller);
                 }
@@ -158,12 +174,12 @@
         }
 
         @Override
-        public int deliverNewSession(IBinder token, IVoiceInteractionSession session,
+        public boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
                 IVoiceInteractor interactor) {
             synchronized (this) {
                 if (mImpl == null) {
-                    Slog.w(TAG, "deliverNewSession without running voice interaction service");
-                    return ActivityManager.START_CANCELED;
+                    throw new SecurityException(
+                            "deliverNewSession without running voice interaction service");
                 }
                 final int callingPid = Binder.getCallingPid();
                 final int callingUid = Binder.getCallingUid();
@@ -175,7 +191,43 @@
                     Binder.restoreCallingIdentity(caller);
                 }
             }
+        }
 
+        @Override
+        public int startVoiceActivity(IBinder token, Intent intent, String resolvedType) {
+            synchronized (this) {
+                if (mImpl == null) {
+                    Slog.w(TAG, "startVoiceActivity without running voice interaction service");
+                    return ActivityManager.START_CANCELED;
+                }
+                final int callingPid = Binder.getCallingPid();
+                final int callingUid = Binder.getCallingUid();
+                final long caller = Binder.clearCallingIdentity();
+                try {
+                    return mImpl.startVoiceActivityLocked(callingPid, callingUid, token,
+                            intent, resolvedType);
+                } finally {
+                    Binder.restoreCallingIdentity(caller);
+                }
+            }
+        }
+
+        @Override
+        public void finish(IBinder token) {
+            synchronized (this) {
+                if (mImpl == null) {
+                    Slog.w(TAG, "finish without running voice interaction service");
+                    return;
+                }
+                final int callingPid = Binder.getCallingPid();
+                final int callingUid = Binder.getCallingUid();
+                final long caller = Binder.clearCallingIdentity();
+                try {
+                    mImpl.finishLocked(callingPid, callingUid, token);
+                } finally {
+                    Binder.restoreCallingIdentity(caller);
+                }
+            }
         }
 
         @Override
@@ -207,7 +259,7 @@
 
             @Override public void onChange(boolean selfChange) {
                 synchronized (VoiceInteractionManagerServiceStub.this) {
-                    switchImplementationIfNeededLocked();
+                    switchImplementationIfNeededLocked(false);
                 }
             }
         }
@@ -220,27 +272,25 @@
 
             @Override
             public void onHandleUserStop(Intent intent, int userHandle) {
-                super.onHandleUserStop(intent, userHandle);
             }
 
             @Override
             public void onPackageDisappeared(String packageName, int reason) {
-                super.onPackageDisappeared(packageName, reason);
             }
 
             @Override
             public void onPackageAppeared(String packageName, int reason) {
-                super.onPackageAppeared(packageName, reason);
+                if (mImpl != null && packageName.equals(mImpl.mComponent.getPackageName())) {
+                    switchImplementationIfNeededLocked(true);
+                }
             }
 
             @Override
             public void onPackageModified(String packageName) {
-                super.onPackageModified(packageName);
             }
 
             @Override
             public void onSomePackagesChanged() {
-                super.onSomePackagesChanged();
             }
         };
     }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 6bbd1c1..9b6daad 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -19,9 +19,11 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
@@ -30,6 +32,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionService;
 import android.service.voice.IVoiceInteractionSession;
@@ -37,6 +40,8 @@
 import android.service.voice.VoiceInteractionService;
 import android.service.voice.VoiceInteractionServiceInfo;
 import android.util.Slog;
+import android.view.IWindowManager;
+import android.view.WindowManager;
 import com.android.internal.app.IVoiceInteractor;
 
 import java.io.FileDescriptor;
@@ -55,11 +60,28 @@
     final IActivityManager mAm;
     final VoiceInteractionServiceInfo mInfo;
     final ComponentName mSessionComponentName;
+    final IWindowManager mIWindowManager;
     boolean mBound = false;
     IVoiceInteractionService mService;
 
     SessionConnection mActiveSession;
 
+    final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+                synchronized (mLock) {
+                    if (mActiveSession != null && mActiveSession.mSession != null) {
+                        try {
+                            mActiveSession.mSession.closeSystemDialogs();
+                        } catch (RemoteException e) {
+                        }
+                    }
+                }
+            }
+        }
+    };
+
     final ServiceConnection mConnection = new ServiceConnection() {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
@@ -76,23 +98,26 @@
 
     final class SessionConnection implements ServiceConnection {
         final IBinder mToken = new Binder();
-        final Intent mIntent;
-        final String mResolvedType;
         final Bundle mArgs;
         boolean mBound;
         IVoiceInteractionSessionService mService;
         IVoiceInteractionSession mSession;
         IVoiceInteractor mInteractor;
 
-        SessionConnection(Intent intent, String resolvedType, Bundle args) {
-            mIntent = intent;
-            mResolvedType = resolvedType;
+        SessionConnection(Bundle args) {
             mArgs = args;
             Intent serviceIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
             serviceIntent.setComponent(mSessionComponentName);
             mBound = mContext.bindServiceAsUser(serviceIntent, this,
                     Context.BIND_AUTO_CREATE, new UserHandle(mUser));
-            if (!mBound) {
+            if (mBound) {
+                try {
+                    mIWindowManager.addWindowToken(mToken,
+                            WindowManager.LayoutParams.TYPE_INPUT_METHOD);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Failed adding window token", e);
+                }
+            } else {
                 Slog.w(TAG, "Failed binding to voice interaction session service " + mComponent);
             }
         }
@@ -105,7 +130,7 @@
                     try {
                         mService.newSession(mToken, mArgs);
                     } catch (RemoteException e) {
-                        Slog.w(TAG, "Failed making new session", e);
+                        Slog.w(TAG, "Failed adding window token", e);
                     }
                 }
             }
@@ -118,7 +143,19 @@
 
         public void cancel() {
             if (mBound) {
+                if (mSession != null) {
+                    try {
+                        mSession.destroy();
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, "Voice interation session already dead");
+                    }
+                }
                 mContext.unbindService(this);
+                try {
+                    mIWindowManager.removeWindowToken(mToken);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Failed removing window token", e);
+                }
                 mBound = false;
                 mService = null;
                 mSession = null;
@@ -128,8 +165,6 @@
 
         public void dump(String prefix, PrintWriter pw) {
             pw.print(prefix); pw.print("mToken="); pw.println(mToken);
-            pw.print(prefix); pw.print("mIntent="); pw.println(mIntent);
-                    pw.print(" mResolvedType="); pw.println(mResolvedType);
             pw.print(prefix); pw.print("mArgs="); pw.println(mArgs);
             pw.print(prefix); pw.print("mBound="); pw.println(mBound);
             if (mBound) {
@@ -155,6 +190,7 @@
             Slog.w(TAG, "Voice interaction service not found: " + service);
             mInfo = null;
             mSessionComponentName = null;
+            mIWindowManager = null;
             mValid = false;
             return;
         }
@@ -162,43 +198,67 @@
         if (mInfo.getParseError() != null) {
             Slog.w(TAG, "Bad voice interaction service: " + mInfo.getParseError());
             mSessionComponentName = null;
+            mIWindowManager = null;
             mValid = false;
             return;
         }
         mValid = true;
         mSessionComponentName = new ComponentName(service.getPackageName(),
                 mInfo.getSessionService());
+        mIWindowManager = IWindowManager.Stub.asInterface(
+                ServiceManager.getService(Context.WINDOW_SERVICE));
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+        mContext.registerReceiver(mBroadcastReceiver, filter, null, handler);
     }
 
-    public void startVoiceActivityLocked(int callingPid, int callingUid, Intent intent,
-            String resolvedType, Bundle args) {
+    public void startSessionLocked(int callingPid, int callingUid, Bundle args) {
         if (mActiveSession != null) {
             mActiveSession.cancel();
             mActiveSession = null;
         }
-        mActiveSession = new SessionConnection(intent, resolvedType, args);
-        intent.addCategory(Intent.CATEGORY_VOICE);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+        mActiveSession = new SessionConnection(args);
     }
 
-    public int deliverNewSessionLocked(int callingPid, int callingUid, IBinder token,
+    public boolean deliverNewSessionLocked(int callingPid, int callingUid, IBinder token,
             IVoiceInteractionSession session, IVoiceInteractor interactor) {
+        if (mActiveSession == null || token != mActiveSession.mToken) {
+            Slog.w(TAG, "deliverNewSession does not match active session");
+            return false;
+        }
+        mActiveSession.mSession = session;
+        mActiveSession.mInteractor = interactor;
+        return true;
+    }
+
+    public int startVoiceActivityLocked(int callingPid, int callingUid, IBinder token,
+            Intent intent, String resolvedType) {
         try {
             if (mActiveSession == null || token != mActiveSession.mToken) {
-                Slog.w(TAG, "deliverNewSession does not match active session");
+                Slog.w(TAG, "startVoiceActivity does not match active session");
                 return ActivityManager.START_CANCELED;
             }
-            mActiveSession.mSession = session;
-            mActiveSession.mInteractor = interactor;
+            intent = new Intent(intent);
+            intent.addCategory(Intent.CATEGORY_VOICE);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
             return mAm.startVoiceActivity(mComponent.getPackageName(), callingPid, callingUid,
-                    mActiveSession.mIntent, mActiveSession.mResolvedType,
-                    mActiveSession.mSession, mActiveSession.mInteractor,
+                    intent, resolvedType, mActiveSession.mSession, mActiveSession.mInteractor,
                     0, null, null, null, mUser);
         } catch (RemoteException e) {
             throw new IllegalStateException("Unexpected remote error", e);
         }
     }
 
+
+    public void finishLocked(int callingPid, int callingUid, IBinder token) {
+        if (mActiveSession == null || token != mActiveSession.mToken) {
+            Slog.w(TAG, "finish does not match active session");
+            return;
+        }
+        mActiveSession.cancel();
+        mActiveSession = null;
+    }
+
     public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!mValid) {
             pw.print("  NOT VALID: ");
@@ -234,5 +294,8 @@
             mContext.unbindService(mConnection);
             mBound = false;
         }
+        if (mValid) {
+            mContext.unregisterReceiver(mBroadcastReceiver);
+        }
     }
 }
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 606fcb4..1ee390f 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -797,6 +797,8 @@
             return TelephonyManager.NETWORK_TYPE_LTE;
         case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP:
             return TelephonyManager.NETWORK_TYPE_HSPAP;
+        case ServiceState.RIL_RADIO_TECHNOLOGY_GSM:
+            return TelephonyManager.NETWORK_TYPE_GSM;
         default:
             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
         }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 407a8d1..df972d5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -911,6 +911,8 @@
     public static final int NETWORK_TYPE_EHRPD = 14;
     /** Current network is HSPA+ */
     public static final int NETWORK_TYPE_HSPAP = 15;
+    /** Current network is GSM {@hide} */
+    public static final int NETWORK_TYPE_GSM = 16;
 
     /**
      * @return the NETWORK_TYPE_xxxx for current data connection.
@@ -1002,6 +1004,7 @@
     public static int getNetworkClass(int networkType) {
         switch (networkType) {
             case NETWORK_TYPE_GPRS:
+            case NETWORK_TYPE_GSM:
             case NETWORK_TYPE_EDGE:
             case NETWORK_TYPE_CDMA:
             case NETWORK_TYPE_1xRTT:
@@ -1068,6 +1071,8 @@
                 return "iDEN";
             case NETWORK_TYPE_HSPAP:
                 return "HSPA+";
+            case NETWORK_TYPE_GSM:
+                return "GSM";
             default:
                 return "UNKNOWN";
         }
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 5c2583b..af0d0ad 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -288,6 +288,15 @@
         </activity>
 
         <activity
+                android:name="CirclePropActivity"
+                android:label="Draw/Circle Props">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.hwui.TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="ClearActivity"
                 android:label="Window/Clear">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
new file mode 100644
index 0000000..f060bc8
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.os.Bundle;
+import android.os.Trace;
+import android.view.HardwareCanvas;
+import android.view.RenderNodeAnimator;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.ProgressBar;
+
+import java.util.ArrayList;
+
+public class CirclePropActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final LinearLayout layout = new LinearLayout(this);
+        layout.setOrientation(LinearLayout.VERTICAL);
+
+        ProgressBar spinner = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge);
+        layout.addView(spinner, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+
+        layout.addView(new CircleView(this),
+                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+        setContentView(layout);
+    }
+
+    static class CircleView extends View {
+        static final int DURATION = 500;
+
+        private boolean mToggle = false;
+        ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<RenderNodeAnimator>();
+
+        CanvasProperty<Float> mX;
+        CanvasProperty<Float> mY;
+        CanvasProperty<Float> mRadius;
+        CanvasProperty<Paint> mPaint;
+
+        CircleView(Context c) {
+            super(c);
+            setClickable(true);
+
+            mX = CanvasProperty.createFloat(200.0f);
+            mY = CanvasProperty.createFloat(200.0f);
+            mRadius = CanvasProperty.createFloat(150.0f);
+
+            Paint p = new Paint();
+            p.setAntiAlias(true);
+            p.setColor(0xFFFF0000);
+            p.setStyle(Style.STROKE);
+            p.setStrokeWidth(60.0f);
+            mPaint = CanvasProperty.createPaint(p);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+
+            if (canvas.isHardwareAccelerated()) {
+                HardwareCanvas hwcanvas = (HardwareCanvas) canvas;
+                hwcanvas.drawCircle(mX, mY, mRadius, mPaint);
+            }
+        }
+
+        @Override
+        public boolean performClick() {
+            for (int i = 0; i < mRunningAnimations.size(); i++) {
+                mRunningAnimations.get(i).cancel();
+            }
+            mRunningAnimations.clear();
+
+            mToggle = !mToggle;
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mX, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 400.0f : 200.0f));
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mY, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 600.0f : 200.0f));
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mRadius, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 250.0f : 150.0f));
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mPaint, RenderNodeAnimator.PAINT_ALPHA,
+                    RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 64.0f : 255.0f));
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mPaint, RenderNodeAnimator.PAINT_STROKE_WIDTH,
+                    RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 5.0f : 60.0f));
+
+            for (int i = 0; i < mRunningAnimations.size(); i++) {
+                mRunningAnimations.get(i).start(this);
+            }
+
+            if (mToggle) {
+                post(new Runnable() {
+                    @Override
+                    public void run() {
+                        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "pretendBusy");
+                        try {
+                            Thread.sleep(DURATION);
+                        } catch (InterruptedException e) {
+                        }
+                        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+                    }
+                });
+            }
+
+            return true;
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
index 8c02539..a3f4ddc 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
@@ -57,7 +57,7 @@
             
             mPaint = new Paint();
             mPaint.setAntiAlias(true);
-            mPaint.setColor(0xffffffff);
+            mPaint.setColor(0xff00ffff);
         }
 
         @Override
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
index 5dc3904..2e029f0 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
@@ -119,7 +119,9 @@
     }
 
     private void updateState(int newState) {
-        mPlaybackState.setState(newState);
+        float rate = newState == PlaybackState.PLAYSTATE_PLAYING ? 1 : 0;
+        long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
+        mPlaybackState.setState(newState, position, rate);
         mPerformer.setPlaybackState(mPlaybackState);
     }
 
@@ -132,7 +134,7 @@
         @Override
         public void onError(int type, int extra, Bundle extras, Throwable error) {
             Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
-            mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+            mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, -1, 0);
             if (error != null) {
                 mPlaybackState.setErrorMessage(error.getLocalizedMessage());
             }
@@ -147,34 +149,33 @@
             if (newState != Renderer.STATE_ERROR) {
                 mPlaybackState.setErrorMessage(null);
             }
+            long position = -1;
+            if (mRenderer != null) {
+                position = mRenderer.getSeekPosition();
+            }
             switch (newState) {
                 case Renderer.STATE_ENDED:
                 case Renderer.STATE_STOPPED:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED, position, 0);
                     break;
                 case Renderer.STATE_INIT:
                 case Renderer.STATE_PREPARING:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING, position, 0);
                     break;
                 case Renderer.STATE_ERROR:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0);
                     break;
                 case Renderer.STATE_PAUSED:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, position, 0);
                     break;
                 case Renderer.STATE_PLAYING:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING, position, 1);
                     break;
                 default:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0);
                     mPlaybackState.setErrorMessage("unkown state");
                     break;
             }
-            if (mRenderer != null) {
-                mPlaybackState.setPosition(mRenderer.getSeekPosition());
-            } else {
-                mPlaybackState.setPosition(-1);
-            }
             mPerformer.setPlaybackState(mPlaybackState);
             if (mListener != null) {
                 mListener.onPlayStateChanged(mPlaybackState);
@@ -188,8 +189,8 @@
         @Override
         public void onFocusLost() {
             Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
-            mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED);
-            mPlaybackState.setPosition(mRenderer.getSeekPosition());
+            long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
+            mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, position, 0);
             mPerformer.setPlaybackState(mPlaybackState);
             if (mListener != null) {
                 mListener.onPlayStateChanged(mPlaybackState);
diff --git a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
index 6edcd7d..6537d49 100644
--- a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
+++ b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
@@ -158,30 +158,33 @@
             if (newState != Renderer.STATE_ERROR) {
                 mPlaybackState.setErrorMessage(null);
             }
+            long position = -1;
+            if (mRenderer != null) {
+                position = mRenderer.getSeekPosition();
+            }
             switch (newState) {
                 case Renderer.STATE_ENDED:
                 case Renderer.STATE_STOPPED:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED, position, 0);
                     break;
                 case Renderer.STATE_INIT:
                 case Renderer.STATE_PREPARING:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING, position, 0);
                     break;
                 case Renderer.STATE_ERROR:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0);
                     break;
                 case Renderer.STATE_PAUSED:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, position, 0);
                     break;
                 case Renderer.STATE_PLAYING:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING, position, 1);
                     break;
                 default:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0);
                     mPlaybackState.setErrorMessage("unkown state");
                     break;
             }
-            mPlaybackState.setPosition(mRenderer.getSeekPosition());
 
             mControls.sendPlaybackChangeEvent(mPlaybackState.getState());
         }
@@ -193,8 +196,8 @@
         @Override
         public void onFocusLost() {
             Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
-            mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED);
-            mPlaybackState.setPosition(mRenderer.getSeekPosition());
+            mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, mRenderer.getSeekPosition(), 0);
+            mRenderer.onPause();
         }
 
         @Override
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index 1d209dd..8f9cf58 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -19,8 +19,6 @@
 
 public class MainActivity extends Activity implements OnItemClickListener {
 
-    static final int TRANSLATION_Y = 1;
-    static final int DELTA_TYPE_DELTA = 1;
     static final int DURATION = 400;
 
     static final String KEY_NAME = "name";
@@ -75,7 +73,7 @@
             float delta = (pos - clickedPosition) * 1.1f;
             if (delta == 0) delta = -1;
             RenderNodeAnimator animator = new RenderNodeAnimator(
-                    TRANSLATION_Y, DELTA_TYPE_DELTA, dy * delta);
+                    RenderNodeAnimator.TRANSLATION_Y, RenderNodeAnimator.DELTA_TYPE_DELTA, dy * delta);
             animator.setDuration(DURATION);
             animator.start(child);
         }
diff --git a/tests/VoiceInteraction/res/layout/voice_interaction_session.xml b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
new file mode 100644
index 0000000..9fcbf3e
--- /dev/null
+++ b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
@@ -0,0 +1,38 @@
+<?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_width="fill_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:background="#ffffffff"
+    >
+
+    <TextView android:id="@+id/text"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="32dp"
+        />
+
+    <Button android:id="@+id/start"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/start"
+        />
+
+</LinearLayout>
+
+
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index 008d97b..d40b05f 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -17,6 +17,7 @@
 package com.android.test.voiceinteraction;
 
 import android.content.Intent;
+import android.os.Bundle;
 import android.service.voice.VoiceInteractionService;
 import android.util.Log;
 
@@ -31,7 +32,9 @@
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        startVoiceActivity(new Intent(this, TestInteractionActivity.class), null);
+        Bundle args = new Bundle();
+        args.putParcelable("intent", new Intent(this, TestInteractionActivity.class));
+        startSession(args);
         stopSelf(startId);
         return START_NOT_STICKY;
     }
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index 0fc563b..a3af284 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -17,18 +17,59 @@
 package com.android.test.voiceinteraction;
 
 import android.content.Context;
+import android.content.Intent;
 import android.os.Bundle;
 import android.service.voice.VoiceInteractionSession;
 import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
 
-public class MainInteractionSession extends VoiceInteractionSession {
+public class MainInteractionSession extends VoiceInteractionSession
+        implements View.OnClickListener {
     static final String TAG = "MainInteractionSession";
 
-    final Bundle mArgs;
+    Intent mStartIntent;
+    View mContentView;
+    TextView mText;
+    Button mStartButton;
 
-    MainInteractionSession(Context context, Bundle args) {
+    Request mPendingRequest;
+    boolean mPendingConfirm;
+
+    MainInteractionSession(Context context) {
         super(context);
-        mArgs = args;
+    }
+
+    @Override
+    public void onCreate(Bundle args) {
+        super.onCreate(args);
+        showWindow();
+        mStartIntent = args.getParcelable("intent");
+    }
+
+    @Override
+    public View onCreateContentView() {
+        mContentView = getLayoutInflater().inflate(R.layout.voice_interaction_session, null);
+        mText = (TextView)mContentView.findViewById(R.id.text);
+        mStartButton = (Button)mContentView.findViewById(R.id.start);
+        mStartButton.setOnClickListener(this);
+        return mContentView;
+    }
+
+    public void onClick(View v) {
+        if (mPendingRequest == null) {
+            mStartButton.setEnabled(false);
+            startVoiceActivity(mStartIntent);
+        } else {
+            if (mPendingConfirm) {
+                mPendingRequest.sendConfirmResult(true, null);
+            } else {
+                mPendingRequest.sendCommandResult(true, null);
+            }
+            mPendingRequest = null;
+            mStartButton.setText("Start");
+        }
     }
 
     @Override
@@ -38,14 +79,22 @@
 
     @Override
     public void onConfirm(Caller caller, Request request, String prompt, Bundle extras) {
-        Log.i(TAG, "onConform: prompt=" + prompt + " extras=" + extras);
-        request.sendConfirmResult(true, null);
+        Log.i(TAG, "onConfirm: prompt=" + prompt + " extras=" + extras);
+        mText.setText(prompt);
+        mStartButton.setEnabled(true);
+        mStartButton.setText("Confirm");
+        mPendingRequest = request;
+        mPendingConfirm = true;
     }
 
     @Override
     public void onCommand(Caller caller, Request request, String command, Bundle extras) {
         Log.i(TAG, "onCommand: command=" + command + " extras=" + extras);
-        request.sendCommandResult(true, null);
+        mText.setText("Command: " + command);
+        mStartButton.setEnabled(true);
+        mStartButton.setText("Finish Command");
+        mPendingRequest = request;
+        mPendingConfirm = false;
     }
 
     @Override
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java
index 8864d71..7cf8178 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java
@@ -23,6 +23,6 @@
 public class MainInteractionSessionService extends VoiceInteractionSessionService {
     @Override
     public VoiceInteractionSession onNewSession(Bundle args) {
-        return new MainInteractionSession(this, args);
+        return new MainInteractionSession(this);
     }
 }
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 25bb26e..b445b8a 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1340,7 +1340,6 @@
                                 name,
                                 locale,
                                 SourcePos(in->getPrintableSource(), block.getLineNumber()));
-                        curIsPseudolocalizable = fileIsTranslatable;
                     }
 
                     if (formatted == false16) {
@@ -1352,7 +1351,7 @@
                 curType = string16;
                 curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
                 curIsStyled = true;
-                curIsPseudolocalizable = (translatable != false16);
+                curIsPseudolocalizable = fileIsTranslatable && (translatable != false16);
             } else if (strcmp16(block.getElementName(&len), drawable16.string()) == 0) {
                 curTag = &drawable16;
                 curType = drawable16;
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
index 4bef424..cdb839a 100644
--- a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
@@ -16,6 +16,12 @@
 
 package com.android.internal.view.menu;
 
+import com.android.layoutlib.bridge.android.BridgeContext;
+
+import android.content.Context;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+
 /**
  * An extension of the {@link MenuItemImpl} to store the view cookie also.
  */
@@ -27,6 +33,7 @@
      * at the time of rendering.
      */
     private Object viewCookie;
+    private BridgeContext mContext;
 
     /**
      * Instantiates this menu item.
@@ -34,14 +41,28 @@
     BridgeMenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
             CharSequence title, int showAsAction) {
         super(menu, group, id, categoryOrder, ordering, title, showAsAction);
+        Context context = menu.getContext();
+        if (context instanceof ContextThemeWrapper) {
+            context = ((ContextThemeWrapper) context).getBaseContext();
+        }
+        if (context instanceof BridgeContext) {
+            mContext = ((BridgeContext) context);
+        }
     }
 
-
     public Object getViewCookie() {
         return viewCookie;
     }
 
     public void setViewCookie(Object viewCookie) {
+        // If the menu item has an associated action provider view,
+        // directly set the cookie in the view to cookie map stored in BridgeContext.
+        View actionView = getActionView();
+        if (actionView != null && mContext != null) {
+            mContext.addViewKey(actionView, viewCookie);
+            // We don't need to add the view cookie to the this item now. But there's no harm in
+            // storing it, in case we need it in the future.
+        }
         this.viewCookie = viewCookie;
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
index 08512e7..936ab4f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
@@ -50,6 +50,7 @@
 import android.view.MenuInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.ActionMenuView;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.ListAdapter;
@@ -179,8 +180,9 @@
             Predicate<View> overflowMenuButtonTest = new Predicate<View>() {
                 @Override
                 public boolean apply(View view) {
-                    return view.getClass().getName()
-                            .equals("android.widget.ActionMenuPresenter$OverflowMenuButton");
+                    ViewGroup.LayoutParams lp = view.getLayoutParams();
+                    return lp instanceof ActionMenuView.LayoutParams &&
+                            ((ActionMenuView.LayoutParams) lp).isOverflowButton;
                 }
             };
             View overflowMenu = null;