Merge "Refactored the notification animations, improved stack scroller"
diff --git a/Android.mk b/Android.mk
index 966c64d..c80a9ab 100644
--- a/Android.mk
+++ b/Android.mk
@@ -78,7 +78,6 @@
 	core/java/android/app/IStopUserCallback.aidl \
         core/java/android/app/task/ITaskCallback.aidl \
         core/java/android/app/task/ITaskService.aidl \
-	core/java/android/app/IThumbnailReceiver.aidl \
 	core/java/android/app/IThumbnailRetriever.aidl \
 	core/java/android/app/ITransientNotification.aidl \
 	core/java/android/app/IUiAutomationConnection.aidl \
@@ -157,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 \
@@ -199,6 +199,8 @@
 	core/java/android/service/dreams/IDozeHardware.aidl \
 	core/java/android/service/dreams/IDreamManager.aidl \
 	core/java/android/service/dreams/IDreamService.aidl \
+	core/java/android/service/fingerprint/IFingerprintService.aidl \
+	core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl \
 	core/java/android/service/trust/ITrustAgentService.aidl \
 	core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
 	core/java/android/service/voice/IVoiceInteractionService.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 71dc9f6..a45ddce 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -267,6 +267,7 @@
     field public static final int actionModeSplitBackground = 16843677; // 0x101039d
     field public static final int actionModeStyle = 16843668; // 0x1010394
     field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
+    field public static final int actionOverflowMenuStyle = 16843857; // 0x1010451
     field public static final int actionProviderClass = 16843657; // 0x1010389
     field public static final int actionViewClass = 16843516; // 0x10102fc
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
@@ -1858,28 +1859,28 @@
     field public static final int TextAppearance_Medium = 16973892; // 0x1030044
     field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045
     field public static final int TextAppearance_Quantum = 16974352; // 0x1030210
-    field public static final int TextAppearance_Quantum_Body1 = 16974546; // 0x10302d2
-    field public static final int TextAppearance_Quantum_Body2 = 16974545; // 0x10302d1
-    field public static final int TextAppearance_Quantum_Button = 16974549; // 0x10302d5
-    field public static final int TextAppearance_Quantum_Caption = 16974547; // 0x10302d3
+    field public static final int TextAppearance_Quantum_Body1 = 16974544; // 0x10302d0
+    field public static final int TextAppearance_Quantum_Body2 = 16974543; // 0x10302cf
+    field public static final int TextAppearance_Quantum_Button = 16974547; // 0x10302d3
+    field public static final int TextAppearance_Quantum_Caption = 16974545; // 0x10302d1
     field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974353; // 0x1030211
-    field public static final int TextAppearance_Quantum_Display1 = 16974541; // 0x10302cd
-    field public static final int TextAppearance_Quantum_Display2 = 16974540; // 0x10302cc
-    field public static final int TextAppearance_Quantum_Display3 = 16974539; // 0x10302cb
-    field public static final int TextAppearance_Quantum_Display4 = 16974538; // 0x10302ca
-    field public static final int TextAppearance_Quantum_Headline = 16974542; // 0x10302ce
+    field public static final int TextAppearance_Quantum_Display1 = 16974539; // 0x10302cb
+    field public static final int TextAppearance_Quantum_Display2 = 16974538; // 0x10302ca
+    field public static final int TextAppearance_Quantum_Display3 = 16974537; // 0x10302c9
+    field public static final int TextAppearance_Quantum_Display4 = 16974536; // 0x10302c8
+    field public static final int TextAppearance_Quantum_Headline = 16974540; // 0x10302cc
     field public static final int TextAppearance_Quantum_Inverse = 16974354; // 0x1030212
     field public static final int TextAppearance_Quantum_Large = 16974355; // 0x1030213
     field public static final int TextAppearance_Quantum_Large_Inverse = 16974356; // 0x1030214
     field public static final int TextAppearance_Quantum_Medium = 16974357; // 0x1030215
     field public static final int TextAppearance_Quantum_Medium_Inverse = 16974358; // 0x1030216
-    field public static final int TextAppearance_Quantum_Menu = 16974548; // 0x10302d4
+    field public static final int TextAppearance_Quantum_Menu = 16974546; // 0x10302d2
     field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974359; // 0x1030217
     field public static final int TextAppearance_Quantum_SearchResult_Title = 16974360; // 0x1030218
     field public static final int TextAppearance_Quantum_Small = 16974361; // 0x1030219
     field public static final int TextAppearance_Quantum_Small_Inverse = 16974362; // 0x103021a
-    field public static final int TextAppearance_Quantum_Subhead = 16974544; // 0x10302d0
-    field public static final int TextAppearance_Quantum_Title = 16974543; // 0x10302cf
+    field public static final int TextAppearance_Quantum_Subhead = 16974542; // 0x10302ce
+    field public static final int TextAppearance_Quantum_Title = 16974541; // 0x10302cd
     field public static final int TextAppearance_Quantum_Widget = 16974364; // 0x103021c
     field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974365; // 0x103021d
     field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974366; // 0x103021e
@@ -2329,118 +2330,116 @@
     field public static final int Widget_Quantum_ActionMode = 16974423; // 0x1030257
     field public static final int Widget_Quantum_AutoCompleteTextView = 16974424; // 0x1030258
     field public static final int Widget_Quantum_Button = 16974425; // 0x1030259
-    field public static final int Widget_Quantum_ButtonBar = 16974433; // 0x1030261
-    field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974434; // 0x1030262
+    field public static final int Widget_Quantum_ButtonBar = 16974431; // 0x103025f
+    field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974432; // 0x1030260
     field public static final int Widget_Quantum_Button_Borderless = 16974426; // 0x103025a
     field public static final int Widget_Quantum_Button_Borderless_Small = 16974427; // 0x103025b
     field public static final int Widget_Quantum_Button_Inset = 16974428; // 0x103025c
-    field public static final int Widget_Quantum_Button_Paper = 16974431; // 0x103025f
-    field public static final int Widget_Quantum_Button_Paper_Color = 16974432; // 0x1030260
     field public static final int Widget_Quantum_Button_Small = 16974429; // 0x103025d
     field public static final int Widget_Quantum_Button_Toggle = 16974430; // 0x103025e
-    field public static final int Widget_Quantum_CalendarView = 16974435; // 0x1030263
-    field public static final int Widget_Quantum_CheckedTextView = 16974436; // 0x1030264
-    field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974437; // 0x1030265
-    field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974438; // 0x1030266
-    field public static final int Widget_Quantum_CompoundButton_Star = 16974439; // 0x1030267
-    field public static final int Widget_Quantum_DatePicker = 16974440; // 0x1030268
-    field public static final int Widget_Quantum_DropDownItem = 16974441; // 0x1030269
-    field public static final int Widget_Quantum_DropDownItem_Spinner = 16974442; // 0x103026a
-    field public static final int Widget_Quantum_EditText = 16974443; // 0x103026b
-    field public static final int Widget_Quantum_ExpandableListView = 16974444; // 0x103026c
-    field public static final int Widget_Quantum_FastScroll = 16974445; // 0x103026d
-    field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974446; // 0x103026e
-    field public static final int Widget_Quantum_GridView = 16974447; // 0x103026f
-    field public static final int Widget_Quantum_HorizontalScrollView = 16974448; // 0x1030270
-    field public static final int Widget_Quantum_ImageButton = 16974449; // 0x1030271
-    field public static final int Widget_Quantum_Light = 16974475; // 0x103028b
-    field public static final int Widget_Quantum_Light_ActionBar = 16974476; // 0x103028c
-    field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974477; // 0x103028d
-    field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974478; // 0x103028e
-    field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974479; // 0x103028f
-    field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974480; // 0x1030290
-    field public static final int Widget_Quantum_Light_ActionButton = 16974481; // 0x1030291
-    field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974482; // 0x1030292
-    field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974483; // 0x1030293
-    field public static final int Widget_Quantum_Light_ActionMode = 16974484; // 0x1030294
-    field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974485; // 0x1030295
-    field public static final int Widget_Quantum_Light_Button = 16974486; // 0x1030296
-    field public static final int Widget_Quantum_Light_ButtonBar = 16974494; // 0x103029e
-    field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974495; // 0x103029f
-    field public static final int Widget_Quantum_Light_Button_Borderless = 16974487; // 0x1030297
-    field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974488; // 0x1030298
-    field public static final int Widget_Quantum_Light_Button_Inset = 16974489; // 0x1030299
-    field public static final int Widget_Quantum_Light_Button_Paper = 16974492; // 0x103029c
-    field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974493; // 0x103029d
-    field public static final int Widget_Quantum_Light_Button_Small = 16974490; // 0x103029a
-    field public static final int Widget_Quantum_Light_Button_Toggle = 16974491; // 0x103029b
-    field public static final int Widget_Quantum_Light_CalendarView = 16974496; // 0x10302a0
-    field public static final int Widget_Quantum_Light_CheckedTextView = 16974497; // 0x10302a1
-    field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974498; // 0x10302a2
-    field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974499; // 0x10302a3
-    field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974500; // 0x10302a4
-    field public static final int Widget_Quantum_Light_DropDownItem = 16974501; // 0x10302a5
-    field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974502; // 0x10302a6
-    field public static final int Widget_Quantum_Light_EditText = 16974503; // 0x10302a7
-    field public static final int Widget_Quantum_Light_ExpandableListView = 16974504; // 0x10302a8
-    field public static final int Widget_Quantum_Light_FastScroll = 16974505; // 0x10302a9
-    field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974506; // 0x10302aa
-    field public static final int Widget_Quantum_Light_GridView = 16974507; // 0x10302ab
-    field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974508; // 0x10302ac
-    field public static final int Widget_Quantum_Light_ImageButton = 16974509; // 0x10302ad
-    field public static final int Widget_Quantum_Light_ListPopupWindow = 16974510; // 0x10302ae
-    field public static final int Widget_Quantum_Light_ListView = 16974511; // 0x10302af
-    field public static final int Widget_Quantum_Light_ListView_DropDown = 16974512; // 0x10302b0
-    field public static final int Widget_Quantum_Light_MediaRouteButton = 16974513; // 0x10302b1
-    field public static final int Widget_Quantum_Light_PopupMenu = 16974514; // 0x10302b2
-    field public static final int Widget_Quantum_Light_PopupWindow = 16974515; // 0x10302b3
-    field public static final int Widget_Quantum_Light_ProgressBar = 16974516; // 0x10302b4
-    field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974517; // 0x10302b5
-    field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974518; // 0x10302b6
-    field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974519; // 0x10302b7
-    field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974520; // 0x10302b8
-    field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974521; // 0x10302b9
-    field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974522; // 0x10302ba
-    field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974523; // 0x10302bb
-    field public static final int Widget_Quantum_Light_RatingBar = 16974524; // 0x10302bc
-    field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974525; // 0x10302bd
-    field public static final int Widget_Quantum_Light_RatingBar_Small = 16974526; // 0x10302be
-    field public static final int Widget_Quantum_Light_ScrollView = 16974527; // 0x10302bf
-    field public static final int Widget_Quantum_Light_SeekBar = 16974528; // 0x10302c0
-    field public static final int Widget_Quantum_Light_SegmentedButton = 16974529; // 0x10302c1
-    field public static final int Widget_Quantum_Light_Spinner = 16974531; // 0x10302c3
-    field public static final int Widget_Quantum_Light_StackView = 16974530; // 0x10302c2
-    field public static final int Widget_Quantum_Light_Tab = 16974532; // 0x10302c4
-    field public static final int Widget_Quantum_Light_TabWidget = 16974533; // 0x10302c5
-    field public static final int Widget_Quantum_Light_TextView = 16974534; // 0x10302c6
-    field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974535; // 0x10302c7
-    field public static final int Widget_Quantum_Light_WebTextView = 16974536; // 0x10302c8
-    field public static final int Widget_Quantum_Light_WebView = 16974537; // 0x10302c9
-    field public static final int Widget_Quantum_ListPopupWindow = 16974450; // 0x1030272
-    field public static final int Widget_Quantum_ListView = 16974451; // 0x1030273
-    field public static final int Widget_Quantum_ListView_DropDown = 16974452; // 0x1030274
-    field public static final int Widget_Quantum_MediaRouteButton = 16974453; // 0x1030275
-    field public static final int Widget_Quantum_PopupMenu = 16974454; // 0x1030276
-    field public static final int Widget_Quantum_PopupWindow = 16974455; // 0x1030277
-    field public static final int Widget_Quantum_ProgressBar = 16974456; // 0x1030278
-    field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974457; // 0x1030279
-    field public static final int Widget_Quantum_ProgressBar_Large = 16974458; // 0x103027a
-    field public static final int Widget_Quantum_ProgressBar_Small = 16974459; // 0x103027b
-    field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974460; // 0x103027c
-    field public static final int Widget_Quantum_RatingBar = 16974461; // 0x103027d
-    field public static final int Widget_Quantum_RatingBar_Indicator = 16974462; // 0x103027e
-    field public static final int Widget_Quantum_RatingBar_Small = 16974463; // 0x103027f
-    field public static final int Widget_Quantum_ScrollView = 16974464; // 0x1030280
-    field public static final int Widget_Quantum_SeekBar = 16974465; // 0x1030281
-    field public static final int Widget_Quantum_SegmentedButton = 16974466; // 0x1030282
-    field public static final int Widget_Quantum_Spinner = 16974468; // 0x1030284
-    field public static final int Widget_Quantum_StackView = 16974467; // 0x1030283
-    field public static final int Widget_Quantum_Tab = 16974469; // 0x1030285
-    field public static final int Widget_Quantum_TabWidget = 16974470; // 0x1030286
-    field public static final int Widget_Quantum_TextView = 16974471; // 0x1030287
-    field public static final int Widget_Quantum_TextView_SpinnerItem = 16974472; // 0x1030288
-    field public static final int Widget_Quantum_WebTextView = 16974473; // 0x1030289
-    field public static final int Widget_Quantum_WebView = 16974474; // 0x103028a
+    field public static final int Widget_Quantum_CalendarView = 16974433; // 0x1030261
+    field public static final int Widget_Quantum_CheckedTextView = 16974434; // 0x1030262
+    field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974435; // 0x1030263
+    field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974436; // 0x1030264
+    field public static final int Widget_Quantum_CompoundButton_Star = 16974437; // 0x1030265
+    field public static final int Widget_Quantum_DatePicker = 16974438; // 0x1030266
+    field public static final int Widget_Quantum_DropDownItem = 16974439; // 0x1030267
+    field public static final int Widget_Quantum_DropDownItem_Spinner = 16974440; // 0x1030268
+    field public static final int Widget_Quantum_EditText = 16974441; // 0x1030269
+    field public static final int Widget_Quantum_ExpandableListView = 16974442; // 0x103026a
+    field public static final int Widget_Quantum_FastScroll = 16974443; // 0x103026b
+    field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974444; // 0x103026c
+    field public static final int Widget_Quantum_GridView = 16974445; // 0x103026d
+    field public static final int Widget_Quantum_HorizontalScrollView = 16974446; // 0x103026e
+    field public static final int Widget_Quantum_ImageButton = 16974447; // 0x103026f
+    field public static final int Widget_Quantum_Light = 16974474; // 0x103028a
+    field public static final int Widget_Quantum_Light_ActionBar = 16974475; // 0x103028b
+    field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974476; // 0x103028c
+    field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974477; // 0x103028d
+    field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974478; // 0x103028e
+    field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974479; // 0x103028f
+    field public static final int Widget_Quantum_Light_ActionButton = 16974480; // 0x1030290
+    field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974481; // 0x1030291
+    field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974482; // 0x1030292
+    field public static final int Widget_Quantum_Light_ActionMode = 16974483; // 0x1030293
+    field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974484; // 0x1030294
+    field public static final int Widget_Quantum_Light_Button = 16974485; // 0x1030295
+    field public static final int Widget_Quantum_Light_ButtonBar = 16974491; // 0x103029b
+    field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974492; // 0x103029c
+    field public static final int Widget_Quantum_Light_Button_Borderless = 16974486; // 0x1030296
+    field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974487; // 0x1030297
+    field public static final int Widget_Quantum_Light_Button_Inset = 16974488; // 0x1030298
+    field public static final int Widget_Quantum_Light_Button_Small = 16974489; // 0x1030299
+    field public static final int Widget_Quantum_Light_Button_Toggle = 16974490; // 0x103029a
+    field public static final int Widget_Quantum_Light_CalendarView = 16974493; // 0x103029d
+    field public static final int Widget_Quantum_Light_CheckedTextView = 16974494; // 0x103029e
+    field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974495; // 0x103029f
+    field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974496; // 0x10302a0
+    field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974497; // 0x10302a1
+    field public static final int Widget_Quantum_Light_DropDownItem = 16974498; // 0x10302a2
+    field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974499; // 0x10302a3
+    field public static final int Widget_Quantum_Light_EditText = 16974500; // 0x10302a4
+    field public static final int Widget_Quantum_Light_ExpandableListView = 16974501; // 0x10302a5
+    field public static final int Widget_Quantum_Light_FastScroll = 16974502; // 0x10302a6
+    field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974503; // 0x10302a7
+    field public static final int Widget_Quantum_Light_GridView = 16974504; // 0x10302a8
+    field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974505; // 0x10302a9
+    field public static final int Widget_Quantum_Light_ImageButton = 16974506; // 0x10302aa
+    field public static final int Widget_Quantum_Light_ListPopupWindow = 16974507; // 0x10302ab
+    field public static final int Widget_Quantum_Light_ListView = 16974508; // 0x10302ac
+    field public static final int Widget_Quantum_Light_ListView_DropDown = 16974509; // 0x10302ad
+    field public static final int Widget_Quantum_Light_MediaRouteButton = 16974510; // 0x10302ae
+    field public static final int Widget_Quantum_Light_PopupMenu = 16974511; // 0x10302af
+    field public static final int Widget_Quantum_Light_PopupMenu_Overflow = 16974512; // 0x10302b0
+    field public static final int Widget_Quantum_Light_PopupWindow = 16974513; // 0x10302b1
+    field public static final int Widget_Quantum_Light_ProgressBar = 16974514; // 0x10302b2
+    field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974515; // 0x10302b3
+    field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974516; // 0x10302b4
+    field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974517; // 0x10302b5
+    field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974518; // 0x10302b6
+    field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974519; // 0x10302b7
+    field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974520; // 0x10302b8
+    field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974521; // 0x10302b9
+    field public static final int Widget_Quantum_Light_RatingBar = 16974522; // 0x10302ba
+    field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974523; // 0x10302bb
+    field public static final int Widget_Quantum_Light_RatingBar_Small = 16974524; // 0x10302bc
+    field public static final int Widget_Quantum_Light_ScrollView = 16974525; // 0x10302bd
+    field public static final int Widget_Quantum_Light_SeekBar = 16974526; // 0x10302be
+    field public static final int Widget_Quantum_Light_SegmentedButton = 16974527; // 0x10302bf
+    field public static final int Widget_Quantum_Light_Spinner = 16974529; // 0x10302c1
+    field public static final int Widget_Quantum_Light_StackView = 16974528; // 0x10302c0
+    field public static final int Widget_Quantum_Light_Tab = 16974530; // 0x10302c2
+    field public static final int Widget_Quantum_Light_TabWidget = 16974531; // 0x10302c3
+    field public static final int Widget_Quantum_Light_TextView = 16974532; // 0x10302c4
+    field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974533; // 0x10302c5
+    field public static final int Widget_Quantum_Light_WebTextView = 16974534; // 0x10302c6
+    field public static final int Widget_Quantum_Light_WebView = 16974535; // 0x10302c7
+    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_PopupMenu_Overflow = 16974453; // 0x1030275
+    field public static final int Widget_Quantum_PopupWindow = 16974454; // 0x1030276
+    field public static final int Widget_Quantum_ProgressBar = 16974455; // 0x1030277
+    field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974456; // 0x1030278
+    field public static final int Widget_Quantum_ProgressBar_Large = 16974457; // 0x1030279
+    field public static final int Widget_Quantum_ProgressBar_Small = 16974458; // 0x103027a
+    field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974459; // 0x103027b
+    field public static final int Widget_Quantum_RatingBar = 16974460; // 0x103027c
+    field public static final int Widget_Quantum_RatingBar_Indicator = 16974461; // 0x103027d
+    field public static final int Widget_Quantum_RatingBar_Small = 16974462; // 0x103027e
+    field public static final int Widget_Quantum_ScrollView = 16974463; // 0x103027f
+    field public static final int Widget_Quantum_SeekBar = 16974464; // 0x1030280
+    field public static final int Widget_Quantum_SegmentedButton = 16974465; // 0x1030281
+    field public static final int Widget_Quantum_Spinner = 16974467; // 0x1030283
+    field public static final int Widget_Quantum_StackView = 16974466; // 0x1030282
+    field public static final int Widget_Quantum_Tab = 16974468; // 0x1030284
+    field public static final int Widget_Quantum_TabWidget = 16974469; // 0x1030285
+    field public static final int Widget_Quantum_TextView = 16974470; // 0x1030286
+    field public static final int Widget_Quantum_TextView_SpinnerItem = 16974471; // 0x1030287
+    field public static final int Widget_Quantum_WebTextView = 16974472; // 0x1030288
+    field public static final int Widget_Quantum_WebView = 16974473; // 0x1030289
     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
@@ -3307,7 +3306,6 @@
     method public void onUserInteraction();
     method protected void onUserLeaveHint();
     method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
-    method public void onWindowDismissed();
     method public void onWindowFocusChanged(boolean);
     method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
     method public void openContextMenu(android.view.View);
@@ -3320,7 +3318,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);
@@ -3338,6 +3335,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);
@@ -3458,8 +3456,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;
@@ -3467,6 +3464,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[]);
@@ -3849,7 +3861,6 @@
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
     method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
-    method public void onWindowDismissed();
     method public void onWindowFocusChanged(boolean);
     method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
     method public void openContextMenu(android.view.View);
@@ -4996,12 +5007,12 @@
   }
 
   public class DevicePolicyManager {
+    method public void addForwardingIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
     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);
@@ -5299,6 +5310,7 @@
     field public static final int RESIZE_VERTICAL = 2; // 0x2
     field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
     field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
+    field public static final int WIDGET_CATEGORY_RECENTS = 4; // 0x4
     field public int autoAdvanceViewId;
     field public android.content.ComponentName configure;
     field public int icon;
@@ -6602,6 +6614,7 @@
     field public static final java.lang.String DISPLAY_SERVICE = "display";
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
+    field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
     field public static final java.lang.String HDMI_CEC_SERVICE = "hdmi_cec";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
@@ -10722,6 +10735,7 @@
     method public void releaseTexImage();
     method public void setDefaultBufferSize(int, int);
     method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener);
+    method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener, android.os.Handler);
     method public void updateTexImage();
   }
 
@@ -11217,19 +11231,11 @@
   public class VectorDrawable extends android.graphics.drawable.Drawable {
     ctor public VectorDrawable();
     method public void draw(android.graphics.Canvas);
-    method public float geAnimationFraction();
     method public int getOpacity();
-    method public int getRepeatCount();
     method public void setAlpha(int);
-    method public void setAnimationFraction(float);
     method public void setColorFilter(android.graphics.ColorFilter);
-    method public void setDuration(long);
     method public void setPadding(android.graphics.Rect);
     method public void setPadding(int, int, int, int);
-    method public void setRepeatCount(int);
-    method public void setRepeatMode(int);
-    method public void start();
-    method public void stop();
   }
 
 }
@@ -11992,6 +11998,8 @@
     field public static final int CONTROL_SCENE_MODE_STEADYPHOTO = 11; // 0xb
     field public static final int CONTROL_SCENE_MODE_SUNSET = 10; // 0xa
     field public static final int CONTROL_SCENE_MODE_THEATRE = 7; // 0x7
+    field public static final int CONTROL_VIDEO_STABILIZATION_MODE_OFF = 0; // 0x0
+    field public static final int CONTROL_VIDEO_STABILIZATION_MODE_ON = 1; // 0x1
     field public static final int EDGE_MODE_FAST = 1; // 0x1
     field public static final int EDGE_MODE_HIGH_QUALITY = 2; // 0x2
     field public static final int EDGE_MODE_OFF = 0; // 0x0
@@ -12165,17 +12173,29 @@
     method public int getSequenceId();
     field public static final android.hardware.camera2.CameraMetadata.Key BLACK_LEVEL_LOCK;
     field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_GAINS;
+    field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_TRANSFORM;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_ANTIBANDING_MODE;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_EXPOSURE_COMPENSATION;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_LOCK;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_MODE;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_PRECAPTURE_TRIGGER;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_REGIONS;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_STATE;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_TARGET_FPS_RANGE;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_REGIONS;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_STATE;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_TRIGGER;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_LOCK;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_REGIONS;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_STATE;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_CAPTURE_INTENT;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_EFFECT_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_MODE;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_SCENE_MODE;
+    field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_VIDEO_STABILIZATION_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key EDGE_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key FLASH_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key FLASH_STATE;
@@ -12206,6 +12226,7 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_PROFILE_TONE_CURVE;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_SENSITIVITY;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEMPERATURE;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_DATA;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TIMESTAMP;
     field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
@@ -12214,6 +12235,7 @@
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP;
+    field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_SCENE_FLICKER;
     field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_BLUE;
     field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_GREEN;
@@ -12221,6 +12243,14 @@
     field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_MODE;
   }
 
+  public final class ColorSpaceTransform {
+    ctor public ColorSpaceTransform(android.hardware.camera2.Rational[]);
+    ctor public ColorSpaceTransform(int[]);
+    method public void copyElements(android.hardware.camera2.Rational[], int);
+    method public void copyElements(int[], int);
+    method public android.hardware.camera2.Rational getElement(int, int);
+  }
+
   public final class Face {
     method public android.graphics.Rect getBounds();
     method public int getId();
@@ -12233,18 +12263,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 {
@@ -12377,6 +12472,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 {
@@ -12418,6 +12514,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;
   }
 
 }
@@ -15203,6 +15300,7 @@
     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";
@@ -24948,7 +25046,6 @@
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public boolean onSearchRequested();
     method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
-    method public void onWindowDismissed();
     method public void onWindowFocusChanged(boolean);
     method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
     method public void setContentView(int);
@@ -24963,6 +25060,36 @@
 
 }
 
+package android.service.fingerprint {
+
+  public class FingerprintManager {
+    ctor public FingerprintManager(android.content.Context);
+    method public void enroll(long);
+    method public void remove(int);
+    method public void startListening(android.service.fingerprint.FingerprintManagerReceiver);
+    method public void stopListening();
+    field protected static final boolean DEBUG = true;
+    field public static final int FINGERPRINT_ERROR = -1; // 0xffffffff
+    field public static final int FINGERPRINT_ERROR_BAD_CAPTURE = 2; // 0x2
+    field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
+    field public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10; // 0xfffffff6
+    field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
+    field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
+    field public static final int FINGERPRINT_SCANNED = 1; // 0x1
+    field public static final int FINGERPRINT_TEMPLATE_ENROLLING = 2; // 0x2
+    field public static final int FINGERPRINT_TEMPLATE_REMOVED = 4; // 0x4
+  }
+
+  public class FingerprintManagerReceiver {
+    ctor public FingerprintManagerReceiver();
+    method public void onEnrollResult(int, int);
+    method public void onError(int);
+    method public void onRemoved(int);
+    method public void onScanned(int, int);
+  }
+
+}
+
 package android.service.notification {
 
   public abstract class NotificationListenerService extends android.app.Service {
@@ -25044,23 +25171,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);
@@ -28712,6 +28869,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);
@@ -30847,7 +31023,7 @@
     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();
@@ -31418,7 +31594,6 @@
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
-    method public abstract void onWindowDismissed();
     method public abstract void onWindowFocusChanged(boolean);
     method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
   }
@@ -31452,26 +31627,17 @@
     method public abstract void onFocusLost(android.view.WindowId);
   }
 
-  public class WindowInsets {
+  public final class WindowInsets {
     ctor public WindowInsets(android.view.WindowInsets);
-    method public android.view.WindowInsets cloneWithSystemWindowInsets(int, int, int, int);
-    method public android.view.WindowInsets cloneWithSystemWindowInsetsConsumed();
-    method public android.view.WindowInsets cloneWithSystemWindowInsetsConsumed(boolean, boolean, boolean, boolean);
-    method public android.view.WindowInsets cloneWithWindowDecorInsets(int, int, int, int);
-    method public android.view.WindowInsets cloneWithWindowDecorInsetsConsumed();
-    method public android.view.WindowInsets cloneWithWindowDecorInsetsConsumed(boolean, boolean, boolean, boolean);
+    method public android.view.WindowInsets consumeSystemWindowInsets();
     method public int getSystemWindowInsetBottom();
     method public int getSystemWindowInsetLeft();
     method public int getSystemWindowInsetRight();
     method public int getSystemWindowInsetTop();
-    method public int getWindowDecorInsetBottom();
-    method public int getWindowDecorInsetLeft();
-    method public int getWindowDecorInsetRight();
-    method public int getWindowDecorInsetTop();
     method public boolean hasInsets();
     method public boolean hasSystemWindowInsets();
-    method public boolean hasWindowDecorInsets();
     method public boolean isRound();
+    method public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int);
   }
 
   public abstract interface WindowManager implements android.view.ViewManager {
@@ -32695,6 +32861,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();
@@ -32788,6 +32964,16 @@
     method public boolean hasMimeType(java.lang.String);
   }
 
+  public abstract interface PermissionRequest {
+    method public abstract void deny();
+    method public abstract android.net.Uri getOrigin();
+    method public abstract long getResources();
+    method public abstract void grant(long);
+    field public static final long RESOURCE_AUDIO_CAPTURE = 4L; // 0x4L
+    field public static final long RESOURCE_GEOLOCATION = 1L; // 0x1L
+    field public static final long RESOURCE_VIDEO_CAPTURE = 2L; // 0x2L
+  }
+
   public abstract interface PluginStub {
     method public abstract android.view.View getEmbeddedView(int, android.content.Context);
     method public abstract android.view.View getFullScreenView(int, android.content.Context);
@@ -32847,6 +33033,8 @@
     method public boolean onJsConfirm(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult);
     method public boolean onJsPrompt(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String, android.webkit.JsPromptResult);
     method public deprecated boolean onJsTimeout();
+    method public void onPermissionRequest(android.webkit.PermissionRequest);
+    method public void onPermissionRequestCanceled(android.webkit.PermissionRequest);
     method public void onProgressChanged(android.webkit.WebView, int);
     method public deprecated void onReachedMaxAppCacheSize(long, long, android.webkit.WebStorage.QuotaUpdater);
     method public void onReceivedIcon(android.webkit.WebView, android.graphics.Bitmap);
@@ -32923,6 +33111,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();
@@ -32967,6 +33156,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);
@@ -32988,6 +33178,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 {
@@ -33080,6 +33273,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();
@@ -33128,6 +33322,7 @@
     method public boolean pageUp(boolean);
     method public void pauseTimers();
     method public void postUrl(java.lang.String, byte[]);
+    method public void preauthorizePermission(android.net.Uri, long);
     method public void reload();
     method public void removeJavascriptInterface(java.lang.String);
     method public void requestFocusNodeHref(android.os.Message);
@@ -33196,6 +33391,7 @@
     method public void onLoadResource(android.webkit.WebView, java.lang.String);
     method public void onPageFinished(android.webkit.WebView, java.lang.String);
     method public void onPageStarted(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
+    method public void onReceivedClientCertRequest(android.webkit.WebView, android.webkit.ClientCertRequest);
     method public void onReceivedError(android.webkit.WebView, int, java.lang.String, java.lang.String);
     method public void onReceivedHttpAuthRequest(android.webkit.WebView, android.webkit.HttpAuthHandler, java.lang.String, java.lang.String);
     method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
@@ -49410,6 +49606,7 @@
     method public abstract boolean getEnableSessionCreation();
     method public abstract java.lang.String[] getEnabledCipherSuites();
     method public abstract java.lang.String[] getEnabledProtocols();
+    method public javax.net.ssl.SSLSession getHandshakeSession();
     method public abstract javax.net.ssl.SSLEngineResult.HandshakeStatus getHandshakeStatus();
     method public abstract boolean getNeedClientAuth();
     method public java.lang.String getPeerHost();
@@ -49483,10 +49680,12 @@
     ctor public SSLParameters(java.lang.String[]);
     ctor public SSLParameters(java.lang.String[], java.lang.String[]);
     method public java.lang.String[] getCipherSuites();
+    method public java.lang.String getEndpointIdentificationAlgorithm();
     method public boolean getNeedClientAuth();
     method public java.lang.String[] getProtocols();
     method public boolean getWantClientAuth();
     method public void setCipherSuites(java.lang.String[]);
+    method public void setEndpointIdentificationAlgorithm(java.lang.String);
     method public void setNeedClientAuth(boolean);
     method public void setProtocols(java.lang.String[]);
     method public void setWantClientAuth(boolean);
@@ -49587,6 +49786,7 @@
     method public abstract boolean getEnableSessionCreation();
     method public abstract java.lang.String[] getEnabledCipherSuites();
     method public abstract java.lang.String[] getEnabledProtocols();
+    method public javax.net.ssl.SSLSession getHandshakeSession();
     method public abstract boolean getNeedClientAuth();
     method public javax.net.ssl.SSLParameters getSSLParameters();
     method public abstract javax.net.ssl.SSLSession getSession();
@@ -49642,6 +49842,14 @@
     method public java.lang.String chooseEngineServerAlias(java.lang.String, java.security.Principal[], javax.net.ssl.SSLEngine);
   }
 
+  public abstract class X509ExtendedTrustManager implements javax.net.ssl.X509TrustManager {
+    ctor public X509ExtendedTrustManager();
+    method public abstract void checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String, java.net.Socket) throws java.security.cert.CertificateException;
+    method public abstract void checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String, javax.net.ssl.SSLEngine) throws java.security.cert.CertificateException;
+    method public abstract void checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, java.net.Socket) throws java.security.cert.CertificateException;
+    method public abstract void checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, javax.net.ssl.SSLEngine) throws java.security.cert.CertificateException;
+  }
+
   public abstract interface X509KeyManager implements javax.net.ssl.KeyManager {
     method public abstract java.lang.String chooseClientAlias(java.lang.String[], java.security.Principal[], java.net.Socket);
     method public abstract java.lang.String chooseServerAlias(java.lang.String, java.security.Principal[], java.net.Socket);
diff --git a/core/java/android/animation/TypeEvaluator.java b/core/java/android/animation/TypeEvaluator.java
index 2640457..429c435 100644
--- a/core/java/android/animation/TypeEvaluator.java
+++ b/core/java/android/animation/TypeEvaluator.java
@@ -29,7 +29,7 @@
     /**
      * This function returns the result of linearly interpolating the start and end values, with
      * <code>fraction</code> representing the proportion between the start and end values. The
-     * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
+     * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
      * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
      * and <code>t</code> is <code>fraction</code>.
      *
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8981c88..af3a92c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -655,7 +655,8 @@
 public class Activity extends ContextThemeWrapper
         implements LayoutInflater.Factory2,
         Window.Callback, KeyEvent.Callback,
-        OnCreateContextMenuListener, ComponentCallbacks2 {
+        OnCreateContextMenuListener, ComponentCallbacks2,
+        Window.OnWindowDismissedCallback {
     private static final String TAG = "Activity";
     private static final boolean DEBUG_LIFECYCLE = false;
 
@@ -2519,7 +2520,9 @@
 
     /**
      * Called when the main window associated with the activity has been dismissed.
+     * @hide
      */
+    @Override
     public void onWindowDismissed() {
         finish();
     }
@@ -3493,6 +3496,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 +4792,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) {
         }
     }
@@ -5432,6 +5440,7 @@
         
         mWindow = PolicyManager.makeNewWindow(this);
         mWindow.setCallback(this);
+        mWindow.setOnWindowDismissedCallback(this);
         mWindow.getLayoutInflater().setPrivateFactory(this);
         if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
             mWindow.setSoftInputMode(info.softInputMode);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9239faf..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;
+        }
     }
 
     /**
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 3c1455b..3eb2fea 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -30,6 +31,7 @@
 import android.transition.TransitionSet;
 import android.util.ArrayMap;
 import android.util.Pair;
+import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroupOverlay;
@@ -138,6 +140,10 @@
     private static final String KEY_HEIGHT = "shared_element:height";
     private static final String KEY_NAME = "shared_element:name";
     private static final String KEY_BITMAP = "shared_element:bitmap";
+    private static final String KEY_SCALE_TYPE = "shared_element:scaleType";
+    private static final String KEY_IMAGE_MATRIX = "shared_element:imageMatrix";
+
+    private static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values();
 
     /**
      * Sent by the exiting coordinator (either EnterTransitionCoordinator
@@ -322,7 +328,8 @@
         final ArrayList<View> accepted = new ArrayList<View>();
         final ArrayList<View> rejected = new ArrayList<View>();
         createSharedElementImages(accepted, rejected, sharedElementNames, state);
-        setSharedElementState(state, accepted);
+        ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalImageViewState =
+                setSharedElementState(state, accepted);
         handleRejected(rejected);
 
         if (getViewsTransition() != null) {
@@ -331,6 +338,7 @@
         setViewVisibility(mSharedElements, View.VISIBLE);
         Transition transition = beginTransition(mEnteringViews, true, allowOverlappingTransitions(),
                 true);
+        setOriginalImageViewState(originalImageViewState);
 
         if (allowOverlappingTransitions()) {
             onStartEnterTransition(transition, mEnteringViews);
@@ -568,15 +576,22 @@
         mEpicenterCallback.setEpicenter(epicenter);
     }
 
-    private void setSharedElementState(Bundle sharedElementState,
-            final ArrayList<View> acceptedOverlayViews) {
+    private ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> setSharedElementState(
+            Bundle sharedElementState, final ArrayList<View> acceptedOverlayViews) {
+        ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalImageState =
+                new ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>>();
         final int[] tempLoc = new int[2];
         if (sharedElementState != null) {
             for (int i = 0; i < mSharedElements.size(); i++) {
                 View sharedElement = mSharedElements.get(i);
+                String name = mTargetSharedNames.get(i);
+                Pair<ImageView.ScaleType, Matrix> originalState = getOldImageState(sharedElement,
+                        name, sharedElementState);
+                if (originalState != null) {
+                    originalImageState.put((ImageView) sharedElement, originalState);
+                }
                 View parent = (View) sharedElement.getParent();
                 parent.getLocationOnScreen(tempLoc);
-                String name = mTargetSharedNames.get(i);
                 setSharedElementState(sharedElement, name, sharedElementState, tempLoc);
                 sharedElement.requestLayout();
             }
@@ -596,6 +611,29 @@
                     }
                 }
         );
+        return originalImageState;
+    }
+
+    private static Pair<ImageView.ScaleType, Matrix> getOldImageState(View view, String name,
+            Bundle transitionArgs) {
+        if (!(view instanceof ImageView)) {
+            return null;
+        }
+        Bundle bundle = transitionArgs.getBundle(name);
+        int scaleTypeInt = bundle.getInt(KEY_SCALE_TYPE, -1);
+        if (scaleTypeInt < 0) {
+            return null;
+        }
+
+        ImageView imageView = (ImageView) view;
+        ImageView.ScaleType originalScaleType = imageView.getScaleType();
+
+        Matrix originalMatrix = null;
+        if (originalScaleType == ImageView.ScaleType.MATRIX) {
+            originalMatrix = new Matrix(imageView.getImageMatrix());
+        }
+
+        return Pair.create(originalScaleType, originalMatrix);
     }
 
     /**
@@ -614,6 +652,21 @@
             return;
         }
 
+        if (view instanceof ImageView) {
+            int scaleTypeInt = sharedElementBundle.getInt(KEY_SCALE_TYPE, -1);
+            if (scaleTypeInt >= 0) {
+                ImageView imageView = (ImageView) view;
+                ImageView.ScaleType scaleType = SCALE_TYPE_VALUES[scaleTypeInt];
+                imageView.setScaleType(scaleType);
+                if (scaleType == ImageView.ScaleType.MATRIX) {
+                    float[] matrixValues = sharedElementBundle.getFloatArray(KEY_IMAGE_MATRIX);
+                    Matrix matrix = new Matrix();
+                    matrix.setValues(matrixValues);
+                    imageView.setImageMatrix(matrix);
+                }
+            }
+        }
+
         float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
         view.setTranslationZ(z);
 
@@ -666,6 +719,17 @@
         view.draw(canvas);
         sharedElementBundle.putParcelable(KEY_BITMAP, bitmap);
 
+        if (view instanceof ImageView) {
+            ImageView imageView = (ImageView) view;
+            int scaleTypeInt = scaleTypeToInt(imageView.getScaleType());
+            sharedElementBundle.putInt(KEY_SCALE_TYPE, scaleTypeInt);
+            if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) {
+                float[] matrix = new float[9];
+                imageView.getImageMatrix().getValues(matrix);
+                sharedElementBundle.putFloatArray(KEY_IMAGE_MATRIX, matrix);
+            }
+        }
+
         transitionArgs.putBundle(name, sharedElementBundle);
     }
 
@@ -829,6 +893,25 @@
         }
     }
 
+    private static void setOriginalImageViewState(
+            ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalState) {
+        for (int i = 0; i < originalState.size(); i++) {
+            ImageView imageView = originalState.keyAt(i);
+            Pair<ImageView.ScaleType, Matrix> state = originalState.valueAt(i);
+            imageView.setScaleType(state.first);
+            imageView.setImageMatrix(state.second);
+        }
+    }
+
+    private static int scaleTypeToInt(ImageView.ScaleType scaleType) {
+        for (int i = 0; i < SCALE_TYPE_VALUES.length; i++) {
+            if (scaleType == SCALE_TYPE_VALUES[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
     private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
         private Rect mEpicenter;
 
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index a810134..097c64e 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -33,6 +33,7 @@
 import android.view.Surface;
 import android.view.TextureView;
 import android.view.TextureView.SurfaceTextureListener;
+import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import dalvik.system.CloseGuard;
@@ -51,6 +52,7 @@
     private int mWidth;
     private int mHeight;
     private Surface mSurface;
+    private int mLastVisibility;
 
     // Only one IIntentSender or Intent may be queued at a time. Most recent one wins.
     IIntentSender mQueuedPendingIntent;
@@ -95,6 +97,8 @@
         mMetrics = new DisplayMetrics();
         wm.getDefaultDisplay().getMetrics(mMetrics);
 
+        mLastVisibility = getVisibility();
+
         if (DEBUG) Log.v(TAG, "ctor()");
     }
 
@@ -103,6 +107,26 @@
         mTextureView.layout(0, 0, r - l, b - t);
     }
 
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+
+        if (mSurface != null) {
+            try {
+                if (visibility == View.GONE) {
+                    mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi);
+                } else if (mLastVisibility == View.GONE) {
+                    // Don't change surface when going between View.VISIBLE and View.INVISIBLE.
+                    mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi);
+                }
+            } catch (RemoteException e) {
+                throw new RuntimeException(
+                        "ActivityView: Unable to set surface of ActivityContainer. " + e);
+            }
+        }
+        mLastVisibility = visibility;
+    }
+
     private boolean injectInputEvent(InputEvent event) {
         return mActivityContainer != null && mActivityContainer.injectEvent(event);
     }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index ab62427..efd3d86 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1440,6 +1440,31 @@
         return null;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int userIdOrig,
+            int userIdDest) {
+        try {
+            mPM.addForwardingIntentFilter(filter, removable, userIdOrig, userIdDest);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void clearForwardingIntentFilters(int userIdOrig) {
+        try {
+            mPM.clearForwardingIntentFilters(userIdOrig);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
     private final ContextImpl mContext;
     private final IPackageManager mPM;
 
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 a4b2651..c621696 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -106,6 +106,9 @@
 import android.os.storage.StorageManager;
 import android.print.IPrintManager;
 import android.print.PrintManager;
+import android.service.fingerprint.FingerprintManager;
+import android.service.fingerprint.FingerprintManagerReceiver;
+import android.service.fingerprint.FingerprintService;
 import android.telephony.TelephonyManager;
 import android.tv.ITvInputManager;
 import android.tv.TvInputManager;
@@ -451,6 +454,11 @@
                     return new KeyguardManager();
                 }});
 
+        registerService(FINGERPRINT_SERVICE, new ServiceFetcher() {
+            public Object createService(ContextImpl ctx) {
+                return new FingerprintManager(ctx);
+            }});
+
         registerService(LAYOUT_INFLATER_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
@@ -473,14 +481,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,
-                                outerContext.getResources().selectSystemTheme(0,
+                                Resources.selectSystemTheme(0,
                                         outerContext.getApplicationInfo().targetSdkVersion,
-                                        com.android.internal.R.array.system_theme_sdks,
-                                        com.android.internal.R.array.system_theme_dialog_styles)),
+                                        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)),
                         ctx.mMainThread.getHandler());
                 }});
 
@@ -731,7 +739,7 @@
     @Override
     public Resources.Theme getTheme() {
         if (mTheme == null) {
-            mThemeResource = mResources.selectDefaultTheme(mThemeResource,
+            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
                     getOuterContext().getApplicationInfo().targetSdkVersion);
             mTheme = mResources.newTheme();
             mTheme.applyStyle(mThemeResource, true);
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 07583fd..12d4513 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -79,7 +79,7 @@
  * </div>
  */
 public class Dialog implements DialogInterface, Window.Callback,
-        KeyEvent.Callback, OnCreateContextMenuListener {
+        KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback {
     private static final String TAG = "Dialog";
     private Activity mOwnerActivity;
     
@@ -165,6 +165,7 @@
         Window w = PolicyManager.makeNewWindow(mContext);
         mWindow = w;
         w.setCallback(this);
+        w.setOnWindowDismissedCallback(this);
         w.setWindowManager(mWindowManager, null, null);
         w.setGravity(Gravity.CENTER);
         mListenersHandler = new ListenersHandler(this);
@@ -708,6 +709,8 @@
     public void onDetachedFromWindow() {
     }
 
+    /** @hide */
+    @Override
     public void onWindowDismissed() {
         dismiss();
     }
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/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/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6f68dfb..929bf65 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -173,12 +173,12 @@
     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.
+     * Flag for {@link #addForwardingIntentFilter}: 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
+     * Flag for {@link #addForwardingIntentFilter}: the intents will be forwarded to the managed
      * profile.
      */
     public static int FLAG_TO_MANAGED_PROFILE = 0x0002;
@@ -1949,10 +1949,10 @@
      * @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) {
+    public void addForwardingIntentFilter(ComponentName admin, IntentFilter filter, int flags) {
         if (mService != null) {
             try {
-                mService.forwardMatchingIntents(admin, filter, flags);
+                mService.addForwardingIntentFilter(admin, filter, flags);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1960,7 +1960,7 @@
     }
 
     /**
-     * Called by a profile owner to remove all the forwarding intent filters from the current user
+     * Called by a profile owner to remove the forwarding intent filters from the current user
      * and from the owner.
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      */
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 495a5f9..e3090b6 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -120,6 +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 addForwardingIntentFilter(in ComponentName admin, in IntentFilter filter, int flags);
     void clearForwardingIntentFilters(in ComponentName admin);
 }
diff --git a/core/java/android/app/task/TaskParams.java b/core/java/android/app/task/TaskParams.java
index 429281c..e2eafd8 100644
--- a/core/java/android/app/task/TaskParams.java
+++ b/core/java/android/app/task/TaskParams.java
@@ -32,8 +32,7 @@
     private final IBinder mCallback;
 
     /**
-     * @return The unique id of this task, specified at creation time using
-     * {@link android.content.Task.Builder#Builder(int, Class)}.
+     * @return The unique id of this task, specified at creation time.
      */
     public int getTaskId() {
         return taskId;
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index dd3a871..d3e9089 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -181,7 +181,8 @@
      * A bundle extra that hints to the AppWidgetProvider the category of host that owns this
      * this widget. Can have the value {@link
      * AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
-     * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}.
+     * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD} or {@link
+     * AppWidgetProviderInfo#WIDGET_CATEGORY_RECENTS}.
      */
     public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
 
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 4b33799..8b9c7f0 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -54,6 +54,11 @@
     public static final int WIDGET_CATEGORY_KEYGUARD = 2;
 
     /**
+     * Indicates that the widget can be displayed within recents.
+     */
+    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/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index a396a05..7f8d0ab 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -512,6 +512,25 @@
      */
     public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
 
+     /**
+      * No preferrence of physical transport for GATT connections to remote dual-mode devices
+      * @hide
+      */
+    public static final int TRANSPORT_AUTO = 0;
+
+    /**
+     * Prefer BR/EDR transport for GATT connections to remote dual-mode devices
+     * @hide
+     */
+   public static final int TRANSPORT_BREDR = 1;
+
+    /**
+     * Prefer LE transport for GATT connections to remote dual-mode devices
+     * @hide
+     */
+   public static final int TRANSPORT_LE = 2;
+
+
     /**
      * Lazy initialization. Guaranteed final after first object constructed, or
      * getService() called.
@@ -1216,6 +1235,27 @@
      */
     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
                                      BluetoothGattCallback callback) {
+        return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO));
+    }
+
+    /**
+     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+     * The callback is used to deliver results to Caller, such as connection status as well
+     * as any further GATT client operations.
+     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+     * GATT client operations.
+     * @param callback GATT callback handler that will receive asynchronous callbacks.
+     * @param autoConnect Whether to directly connect to the remote device (false)
+     *                    or to automatically connect as soon as the remote
+     *                    device becomes available (true).
+     * @param transport preferred transport for GATT connections to remote dual-mode devices
+     *             {@link BluetoothDevice#TRANSPORT_AUTO} or
+     *             {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
+     * @throws IllegalArgumentException if callback is null
+     * @hide
+     */
+    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
+                                     BluetoothGattCallback callback, int transport) {
         // TODO(Bluetooth) check whether platform support BLE
         //     Do the check here or in GattServer?
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -1226,10 +1266,11 @@
                 // BLE is not supported
                 return null;
             }
-            BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this);
+            BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this, transport);
             gatt.connect(autoConnect, callback);
             return gatt;
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
+
 }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index ff3af7c..601d9ee 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -51,6 +51,7 @@
     private int mConnState;
     private final Object mStateLock = new Object();
     private Boolean mDeviceBusy = false;
+    private int mTransport;
 
     private static final int CONN_STATE_IDLE = 0;
     private static final int CONN_STATE_CONNECTING = 1;
@@ -135,7 +136,7 @@
                 }
                 try {
                     mService.clientConnect(mClientIf, mDevice.getAddress(),
-                                           !mAutoConnect); // autoConnect is inverse of "isDirect"
+                                           !mAutoConnect, mTransport); // autoConnect is inverse of "isDirect"
                 } catch (RemoteException e) {
                     Log.e(TAG,"",e);
                 }
@@ -600,10 +601,12 @@
             }
         };
 
-    /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) {
+    /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device,
+                                int transport) {
         mContext = context;
         mService = iGatt;
         mDevice = device;
+        mTransport = transport;
         mServices = new ArrayList<BluetoothGattService>();
 
         mConnState = CONN_STATE_IDLE;
@@ -759,7 +762,7 @@
     public boolean connect() {
         try {
             mService.clientConnect(mClientIf, mDevice.getAddress(),
-                                   false); // autoConnect is inverse of "isDirect"
+                                   false, mTransport); // autoConnect is inverse of "isDirect"
             return true;
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 0c00c06..34e8605 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -50,6 +50,7 @@
 
     private Object mServerIfLock = new Object();
     private int mServerIf;
+    private int mTransport;
     private List<BluetoothGattService> mServices;
 
     private static final int CALLBACK_REG_TIMEOUT = 10000;
@@ -269,12 +270,13 @@
     /**
      * Create a BluetoothGattServer proxy object.
      */
-    /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt) {
+    /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt, int transport) {
         mContext = context;
         mService = iGatt;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
         mCallback = null;
         mServerIf = 0;
+        mTransport = transport;
         mServices = new ArrayList<BluetoothGattService>();
     }
 
@@ -401,7 +403,7 @@
 
         try {
             mService.serverConnect(mServerIf, device.getAddress(),
-                               autoConnect ? false : true); // autoConnect is inverse of "isDirect"
+                               autoConnect ? false : true,mTransport); // autoConnect is inverse of "isDirect"
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
             return false;
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 172f3bc..b1618cf3 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -194,6 +194,26 @@
      */
     public BluetoothGattServer openGattServer(Context context,
                                               BluetoothGattServerCallback callback) {
+
+        return (openGattServer (context, callback, BluetoothDevice.TRANSPORT_AUTO));
+    }
+
+    /**
+     * Open a GATT Server
+     * The callback is used to deliver results to Caller, such as connection status as well
+     * as the results of any other GATT server operations.
+     * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
+     * to conduct GATT server operations.
+     * @param context App context
+     * @param callback GATT server callback handler that will receive asynchronous callbacks.
+     * @param transport preferred transport for GATT connections to remote dual-mode devices
+     *             {@link BluetoothDevice#TRANSPORT_AUTO} or
+     *             {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
+     * @return BluetoothGattServer instance
+     * @hide
+     */
+    public BluetoothGattServer openGattServer(Context context,
+                                              BluetoothGattServerCallback callback,int transport) {
         if (context == null || callback == null) {
             throw new IllegalArgumentException("null parameter: " + context + " " + callback);
         }
@@ -208,7 +228,7 @@
                 Log.e(TAG, "Fail to get GATT Server connection");
                 return null;
             }
-            BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt);
+            BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt,transport);
             Boolean regStatus = mGattServer.registerCallback(callback);
             return regStatus? mGattServer : null;
         } catch (RemoteException e) {
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index f532f7c..00fd7ce 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -325,6 +325,7 @@
             }
         } catch (RemoteException e) {
             Log.e(TAG, Log.getStackTraceString(new Throwable()));
+            throw new IOException("unable to send RPC: " + e.getMessage());
         }
     }
 
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 6dd551e..a0b603e 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -53,6 +53,9 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = true;
 
+    // Event sent to the mBtdtHandler when DHCP fails so we can tear down the network.
+    private static final int EVENT_NETWORK_FAILED = 1;
+
     private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
     private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
     private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
@@ -315,6 +318,7 @@
                     }
                     if (!success) {
                         Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
+                        mBtdtHandler.obtainMessage(EVENT_NETWORK_FAILED).sendToTarget();
                         return;
                     }
                     mLinkProperties = dhcpResults.linkProperties;
@@ -407,6 +411,10 @@
                     if (VDBG) Log.d(TAG, "got EVENT_NETWORK_DISCONNECTED, " + linkProperties);
                     mBtdt.stopReverseTether();
                     break;
+                case EVENT_NETWORK_FAILED:
+                    if (VDBG) Log.d(TAG, "got EVENT_NETWORK_FAILED");
+                    mBtdt.teardown();
+                    break;
             }
         }
     }
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 4b28516..ab53fb0 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -18,6 +18,8 @@
 
 import android.os.ParcelUuid;
 
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.UUID;
@@ -76,6 +78,12 @@
     public static final ParcelUuid BASE_UUID =
             ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
 
+    /** Length of bytes for 16 bit UUID */
+    public static final int UUID_BYTES_16_BIT = 2;
+    /** Length of bytes for 32 bit UUID */
+    public static final int UUID_BYTES_32_BIT = 4;
+    /** Length of bytes for 128 bit UUID */
+    public static final int UUID_BYTES_128_BIT = 16;
 
     public static final ParcelUuid[] RESERVED_UUIDS = {
         AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
@@ -216,15 +224,60 @@
     }
 
     /**
+     * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID,
+     * but the returned UUID is always in 128-bit format.
+     * Note UUID is little endian in Bluetooth.
+     *
+     * @param uuidBytes Byte representation of uuid.
+     * @return {@link ParcelUuid} parsed from bytes.
+     * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed.
+     */
+    public static ParcelUuid parseUuidFrom(byte[] uuidBytes) {
+        if (uuidBytes == null) {
+            throw new IllegalArgumentException("uuidBytes cannot be null");
+        }
+        int length = uuidBytes.length;
+        if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT &&
+                length != UUID_BYTES_128_BIT) {
+            throw new IllegalArgumentException("uuidBytes length invalid - " + length);
+        }
+
+        // Construct a 128 bit UUID.
+        if (length == UUID_BYTES_128_BIT) {
+            ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN);
+            long msb = buf.getLong(8);
+            long lsb = buf.getLong(0);
+            return new ParcelUuid(new UUID(msb, lsb));
+        }
+
+        // For 16 bit and 32 bit UUID we need to convert them to 128 bit value.
+        // 128_bit_value = uuid * 2^96 + BASE_UUID
+        long shortUuid;
+        if (length == UUID_BYTES_16_BIT) {
+            shortUuid = uuidBytes[0] & 0xFF;
+            shortUuid += (uuidBytes[1] & 0xFF) << 8;
+        } else {
+            shortUuid = uuidBytes[0] & 0xFF ;
+            shortUuid += (uuidBytes[1] & 0xFF) << 8;
+            shortUuid += (uuidBytes[2] & 0xFF) << 16;
+            shortUuid += (uuidBytes[3] & 0xFF) << 24;
+        }
+        long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32);
+        long lsb = BASE_UUID.getUuid().getLeastSignificantBits();
+        return new ParcelUuid(new UUID(msb, lsb));
+    }
+
+    /**
      * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid.
+     *
      * @param parcelUuid
      * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise.
      */
     public static boolean isShortUuid(ParcelUuid parcelUuid) {
-      UUID uuid = parcelUuid.getUuid();
-      if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
-        return false;
-      }
-      return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
+        UUID uuid = parcelUuid.getUuid();
+        if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
+            return false;
+        }
+        return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
     }
 }
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index c6b5c3d..49b156d 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -35,7 +35,7 @@
 
     void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
     void unregisterClient(in int clientIf);
-    void clientConnect(in int clientIf, in String address, in boolean isDirect);
+    void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport);
     void clientDisconnect(in int clientIf, in String address);
     void startAdvertising(in int appIf);
     void stopAdvertising();
@@ -77,7 +77,7 @@
 
     void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallback callback);
     void unregisterServer(in int serverIf);
-    void serverConnect(in int servertIf, in String address, in boolean isDirect);
+    void serverConnect(in int servertIf, in String address, in boolean isDirect, in int transport);
     void serverDisconnect(in int serverIf, in String address);
     void beginServiceDeclaration(in int serverIf, in int srvcType,
                             in int srvcInstanceId, in int minHandles,
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index de223a3..7c625bd 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2377,6 +2377,16 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.service.fingerprint.FingerprintManager} for handling management
+     * of fingerprints.
+     *
+     * @see #getSystemService
+     * @see android.app.FingerprintManager
+     */
+    public static final String FINGERPRINT_SERVICE = "fingerprint";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.media.MediaRouter} for controlling and managing
      * routing of media.
      *
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index cf9a296..03eb50f 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -247,7 +247,8 @@
 
     void clearPackagePersistentPreferredActivities(String packageName, int userId);
 
-    void addForwardingIntentFilter(in IntentFilter filter, int userIdOrig, int userIdDest);
+    void addForwardingIntentFilter(in IntentFilter filter, boolean removable, int userIdOrig,
+            int userIdDest);
 
     void clearForwardingIntentFilters(int userIdOrig);
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 484a2a1..1a003ff 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3507,4 +3507,26 @@
         return Environment.getDataDirectory().toString() + "/user/" + userId
                 + "/" + packageName;
     }
+
+    /**
+     * Adds a forwarding intent filter. After calling this method all intents sent from the user
+     * with id userIdOrig can also be be resolved by activities in the user with id userIdDest if
+     * they match the specified intent filter.
+     * @param filter the {@link IntentFilter} the intent has to match to be forwarded
+     * @param removable if set to false, {@link clearForwardingIntents} will not remove this intent
+     * filter
+     * @param userIdOrig user from which the intent can be forwarded
+     * @param userIdDest user to which the intent can be forwarded
+     * @hide
+     */
+    public abstract void addForwardingIntentFilter(IntentFilter filter, boolean removable,
+            int userIdOrig, int userIdDest);
+
+    /**
+     * Clearing all removable {@link ForwardingIntentFilter}s that are set with the given user as
+     * the origin.
+     * @param userIdOrig user from which the intent can be forwarded
+     * @hide
+     */
+    public abstract void clearForwardingIntentFilters(int userIdOrig);
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 1331777..499de17 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -137,45 +137,42 @@
 
     /**
      * 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 int selectDefaultTheme(int curTheme, int targetSdkVersion) {
+    public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
         return selectSystemTheme(curTheme, targetSdkVersion,
-                com.android.internal.R.array.system_theme_sdks,
-                com.android.internal.R.array.system_theme_styles);
+                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);
     }
 
-    /**
-     * 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) {
+    /** @hide */
+    public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo,
+            int dark, int deviceDefault) {
         if (curTheme != 0) {
             return curTheme;
         }
-
-        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.HONEYCOMB) {
+            return orig;
         }
-
-        return defaultThemes.getResourceId(0, 0);
+        if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+            return holo;
+        }
+        if (targetSdkVersion < Build.VERSION_CODES.CUR_DEVELOPMENT) {
+            return dark;
+        }
+        return deviceDefault;
     }
 
     /**
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/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index ba8db3a..6e38a22f 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1295,6 +1295,20 @@
     public static final int CONTROL_SCENE_MODE_BARCODE = 16;
 
     //
+    // Enumeration values for CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
+    //
+
+    /**
+     * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
+     */
+    public static final int CONTROL_VIDEO_STABILIZATION_MODE_OFF = 0;
+
+    /**
+     * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
+     */
+    public static final int CONTROL_VIDEO_STABILIZATION_MODE_ON = 1;
+
+    //
     // Enumeration values for CaptureRequest#EDGE_MODE
     //
 
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index c4e342c..f161f3a 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -831,9 +831,11 @@
      * stabilized</p>
      *
      * @see CaptureRequest#SCALER_CROP_REGION
+     * @see #CONTROL_VIDEO_STABILIZATION_MODE_OFF
+     * @see #CONTROL_VIDEO_STABILIZATION_MODE_ON
      */
-    public static final Key<Boolean> CONTROL_VIDEO_STABILIZATION_MODE =
-            new Key<Boolean>("android.control.videoStabilizationMode", boolean.class);
+    public static final Key<Integer> CONTROL_VIDEO_STABILIZATION_MODE =
+            new Key<Integer>("android.control.videoStabilizationMode", int.class);
 
     /**
      * <p>Operation mode for edge
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d8981c8..1d2d0e9 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -124,6 +124,58 @@
 
 
     /**
+     * <p>The mode control selects how the image data is converted from the
+     * sensor's native color into linear sRGB color.</p>
+     * <p>When auto-white balance is enabled with {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, this
+     * control is overridden by the AWB routine. When AWB is disabled, the
+     * application controls how the color mapping is performed.</p>
+     * <p>We define the expected processing pipeline below. For consistency
+     * across devices, this is always the case with TRANSFORM_MATRIX.</p>
+     * <p>When either FULL or HIGH_QUALITY is used, the camera device may
+     * do additional processing but {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
+     * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform} will still be provided by the
+     * camera device (in the results) and be roughly correct.</p>
+     * <p>Switching to TRANSFORM_MATRIX and using the data provided from
+     * FAST or HIGH_QUALITY will yield a picture with the same white point
+     * as what was produced by the camera device in the earlier frame.</p>
+     * <p>The expected processing pipeline is as follows:</p>
+     * <p><img alt="White balance processing pipeline" src="../../../../images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png" /></p>
+     * <p>The white balance is encoded by two values, a 4-channel white-balance
+     * gain vector (applied in the Bayer domain), and a 3x3 color transform
+     * matrix (applied after demosaic).</p>
+     * <p>The 4-channel white-balance gains are defined as:</p>
+     * <pre><code>{@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} = [ R G_even G_odd B ]
+     * </code></pre>
+     * <p>where <code>G_even</code> is the gain for green pixels on even rows of the
+     * output, and <code>G_odd</code> is the gain for green pixels on the odd rows.
+     * These may be identical for a given camera device implementation; if
+     * the camera device does not support a separate gain for even/odd green
+     * channels, it will use the <code>G_even</code> value, and write <code>G_odd</code> equal to
+     * <code>G_even</code> in the output result metadata.</p>
+     * <p>The matrices for color transforms are defined as a 9-entry vector:</p>
+     * <pre><code>{@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform} = [ I0 I1 I2 I3 I4 I5 I6 I7 I8 ]
+     * </code></pre>
+     * <p>which define a transform from input sensor colors, <code>P_in = [ r g b ]</code>,
+     * to output linear sRGB, <code>P_out = [ r' g' b' ]</code>,</p>
+     * <p>with colors as follows:</p>
+     * <pre><code>r' = I0r + I1g + I2b
+     * g' = I3r + I4g + I5b
+     * b' = I6r + I7g + I8b
+     * </code></pre>
+     * <p>Both the input and output value ranges must match. Overflow/underflow
+     * values are clipped to fit within the range.</p>
+     *
+     * @see CaptureRequest#COLOR_CORRECTION_GAINS
+     * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
+     * @see CaptureRequest#CONTROL_AWB_MODE
+     * @see #COLOR_CORRECTION_MODE_TRANSFORM_MATRIX
+     * @see #COLOR_CORRECTION_MODE_FAST
+     * @see #COLOR_CORRECTION_MODE_HIGH_QUALITY
+     */
+    public static final Key<Integer> COLOR_CORRECTION_MODE =
+            new Key<Integer>("android.colorCorrection.mode", int.class);
+
+    /**
      * <p>A color transform matrix to use to transform
      * from sensor RGB color space to output linear sRGB color space</p>
      * <p>This matrix is either set by the camera device when the request
@@ -176,6 +228,82 @@
             new Key<Integer>("android.control.aePrecaptureId", int.class);
 
     /**
+     * <p>The desired setting for the camera device's auto-exposure
+     * algorithm's antibanding compensation.</p>
+     * <p>Some kinds of lighting fixtures, such as some fluorescent
+     * lights, flicker at the rate of the power supply frequency
+     * (60Hz or 50Hz, depending on country). While this is
+     * typically not noticeable to a person, it can be visible to
+     * a camera device. If a camera sets its exposure time to the
+     * wrong value, the flicker may become visible in the
+     * viewfinder as flicker or in a final captured image, as a
+     * set of variable-brightness bands across the image.</p>
+     * <p>Therefore, the auto-exposure routines of camera devices
+     * include antibanding routines that ensure that the chosen
+     * exposure value will not cause such banding. The choice of
+     * exposure time depends on the rate of flicker, which the
+     * camera device can detect automatically, or the expected
+     * rate can be selected by the application using this
+     * control.</p>
+     * <p>A given camera device may not support all of the possible
+     * options for the antibanding mode. The
+     * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_ANTIBANDING_MODES android.control.aeAvailableAntibandingModes} key contains
+     * the available modes for a given camera device.</p>
+     * <p>The default mode is AUTO, which must be supported by all
+     * camera devices.</p>
+     * <p>If manual exposure control is enabled (by setting
+     * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} or {@link CaptureRequest#CONTROL_MODE android.control.mode} to OFF),
+     * then this setting has no effect, and the application must
+     * ensure it selects exposure times that do not cause banding
+     * issues. The {@link CaptureResult#STATISTICS_SCENE_FLICKER android.statistics.sceneFlicker} key can assist
+     * the application in this.</p>
+     *
+     * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_ANTIBANDING_MODES
+     * @see CaptureRequest#CONTROL_AE_MODE
+     * @see CaptureRequest#CONTROL_MODE
+     * @see CaptureResult#STATISTICS_SCENE_FLICKER
+     * @see #CONTROL_AE_ANTIBANDING_MODE_OFF
+     * @see #CONTROL_AE_ANTIBANDING_MODE_50HZ
+     * @see #CONTROL_AE_ANTIBANDING_MODE_60HZ
+     * @see #CONTROL_AE_ANTIBANDING_MODE_AUTO
+     */
+    public static final Key<Integer> CONTROL_AE_ANTIBANDING_MODE =
+            new Key<Integer>("android.control.aeAntibandingMode", int.class);
+
+    /**
+     * <p>Adjustment to AE target image
+     * brightness</p>
+     * <p>For example, if EV step is 0.333, '6' will mean an
+     * exposure compensation of +2 EV; -3 will mean an exposure
+     * compensation of -1</p>
+     */
+    public static final Key<Integer> CONTROL_AE_EXPOSURE_COMPENSATION =
+            new Key<Integer>("android.control.aeExposureCompensation", int.class);
+
+    /**
+     * <p>Whether AE is currently locked to its latest
+     * calculated values.</p>
+     * <p>Note that even when AE is locked, the flash may be
+     * fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_AUTO_FLASH / ON_ALWAYS_FLASH /
+     * ON_AUTO_FLASH_REDEYE.</p>
+     * <p>If AE precapture is triggered (see {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger})
+     * when AE is already locked, the camera device will not change the exposure time
+     * ({@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}) and sensitivity ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity})
+     * parameters. The flash may be fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}
+     * is ON_AUTO_FLASH/ON_AUTO_FLASH_REDEYE and the scene is too dark. If the
+     * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.</p>
+     * <p>See {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE lock related state transition details.</p>
+     *
+     * @see CaptureRequest#CONTROL_AE_MODE
+     * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
+     * @see CaptureResult#CONTROL_AE_STATE
+     * @see CaptureRequest#SENSOR_EXPOSURE_TIME
+     * @see CaptureRequest#SENSOR_SENSITIVITY
+     */
+    public static final Key<Boolean> CONTROL_AE_LOCK =
+            new Key<Boolean>("android.control.aeLock", boolean.class);
+
+    /**
      * <p>The desired mode for the camera device's
      * auto-exposure routine.</p>
      * <p>This control is only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} is
@@ -237,6 +365,35 @@
             new Key<int[]>("android.control.aeRegions", int[].class);
 
     /**
+     * <p>Range over which fps can be adjusted to
+     * maintain exposure</p>
+     * <p>Only constrains AE algorithm, not manual control
+     * of {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}</p>
+     *
+     * @see CaptureRequest#SENSOR_EXPOSURE_TIME
+     */
+    public static final Key<int[]> CONTROL_AE_TARGET_FPS_RANGE =
+            new Key<int[]>("android.control.aeTargetFpsRange", int[].class);
+
+    /**
+     * <p>Whether the camera device will trigger a precapture
+     * metering sequence when it processes this request.</p>
+     * <p>This entry is normally set to IDLE, or is not
+     * included at all in the request settings. When included and
+     * set to START, the camera device will trigger the autoexposure
+     * precapture metering sequence.</p>
+     * <p>The effect of AE precapture trigger depends on the current
+     * AE mode and state; see {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture
+     * state transition details.</p>
+     *
+     * @see CaptureResult#CONTROL_AE_STATE
+     * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
+     * @see #CONTROL_AE_PRECAPTURE_TRIGGER_START
+     */
+    public static final Key<Integer> CONTROL_AE_PRECAPTURE_TRIGGER =
+            new Key<Integer>("android.control.aePrecaptureTrigger", int.class);
+
+    /**
      * <p>Current state of AE algorithm</p>
      * <p>Switching between or enabling AE modes ({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}) always
      * resets the AE state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
@@ -481,6 +638,24 @@
             new Key<int[]>("android.control.afRegions", int[].class);
 
     /**
+     * <p>Whether the camera device will trigger autofocus for this request.</p>
+     * <p>This entry is normally set to IDLE, or is not
+     * included at all in the request settings.</p>
+     * <p>When included and set to START, the camera device will trigger the
+     * autofocus algorithm. If autofocus is disabled, this trigger has no effect.</p>
+     * <p>When set to CANCEL, the camera device will cancel any active trigger,
+     * and return to its initial AF state.</p>
+     * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what that means for each AF mode.</p>
+     *
+     * @see CaptureResult#CONTROL_AF_STATE
+     * @see #CONTROL_AF_TRIGGER_IDLE
+     * @see #CONTROL_AF_TRIGGER_START
+     * @see #CONTROL_AF_TRIGGER_CANCEL
+     */
+    public static final Key<Integer> CONTROL_AF_TRIGGER =
+            new Key<Integer>("android.control.afTrigger", int.class);
+
+    /**
      * <p>Current state of AF algorithm.</p>
      * <p>Switching between or enabling AF modes ({@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}) always
      * resets the AF state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
@@ -889,6 +1064,16 @@
             new Key<Integer>("android.control.afTriggerId", int.class);
 
     /**
+     * <p>Whether AWB is currently locked to its
+     * latest calculated values.</p>
+     * <p>Note that AWB lock is only meaningful for AUTO
+     * mode; in other modes, AWB is already fixed to a specific
+     * setting.</p>
+     */
+    public static final Key<Boolean> CONTROL_AWB_LOCK =
+            new Key<Boolean>("android.control.awbLock", boolean.class);
+
+    /**
      * <p>Whether AWB is currently setting the color
      * transform fields, and what its illumination target
      * is.</p>
@@ -948,6 +1133,30 @@
             new Key<int[]>("android.control.awbRegions", int[].class);
 
     /**
+     * <p>Information to the camera device 3A (auto-exposure,
+     * auto-focus, auto-white balance) routines about the purpose
+     * of this capture, to help the camera device to decide optimal 3A
+     * strategy.</p>
+     * <p>This control (except for MANUAL) is only effective if
+     * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
+     * <p>ZERO_SHUTTER_LAG must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+     * contains ZSL. MANUAL must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+     * contains MANUAL_SENSOR.</p>
+     *
+     * @see CaptureRequest#CONTROL_MODE
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     * @see #CONTROL_CAPTURE_INTENT_CUSTOM
+     * @see #CONTROL_CAPTURE_INTENT_PREVIEW
+     * @see #CONTROL_CAPTURE_INTENT_STILL_CAPTURE
+     * @see #CONTROL_CAPTURE_INTENT_VIDEO_RECORD
+     * @see #CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT
+     * @see #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG
+     * @see #CONTROL_CAPTURE_INTENT_MANUAL
+     */
+    public static final Key<Integer> CONTROL_CAPTURE_INTENT =
+            new Key<Integer>("android.control.captureIntent", int.class);
+
+    /**
      * <p>Current state of AWB algorithm</p>
      * <p>Switching between or enabling AWB modes ({@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}) always
      * resets the AWB state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
@@ -1078,6 +1287,31 @@
             new Key<Integer>("android.control.awbState", int.class);
 
     /**
+     * <p>A special color effect to apply.</p>
+     * <p>When this mode is set, a color effect will be applied
+     * to images produced by the camera device. The interpretation
+     * and implementation of these color effects is left to the
+     * implementor of the camera device, and should not be
+     * depended on to be consistent (or present) across all
+     * devices.</p>
+     * <p>A color effect will only be applied if
+     * {@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF.</p>
+     *
+     * @see CaptureRequest#CONTROL_MODE
+     * @see #CONTROL_EFFECT_MODE_OFF
+     * @see #CONTROL_EFFECT_MODE_MONO
+     * @see #CONTROL_EFFECT_MODE_NEGATIVE
+     * @see #CONTROL_EFFECT_MODE_SOLARIZE
+     * @see #CONTROL_EFFECT_MODE_SEPIA
+     * @see #CONTROL_EFFECT_MODE_POSTERIZE
+     * @see #CONTROL_EFFECT_MODE_WHITEBOARD
+     * @see #CONTROL_EFFECT_MODE_BLACKBOARD
+     * @see #CONTROL_EFFECT_MODE_AQUA
+     */
+    public static final Key<Integer> CONTROL_EFFECT_MODE =
+            new Key<Integer>("android.control.effectMode", int.class);
+
+    /**
      * <p>Overall mode of 3A control
      * routines.</p>
      * <p>High-level 3A control. When set to OFF, all 3A control
@@ -1106,6 +1340,57 @@
             new Key<Integer>("android.control.mode", int.class);
 
     /**
+     * <p>A camera mode optimized for conditions typical in a particular
+     * capture setting.</p>
+     * <p>This is the mode that that is active when
+     * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY,
+     * these modes will disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
+     * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.</p>
+     * <p>The interpretation and implementation of these scene modes is left
+     * to the implementor of the camera device. Their behavior will not be
+     * consistent across all devices, and any given device may only implement
+     * a subset of these modes.</p>
+     *
+     * @see CaptureRequest#CONTROL_AE_MODE
+     * @see CaptureRequest#CONTROL_AF_MODE
+     * @see CaptureRequest#CONTROL_AWB_MODE
+     * @see CaptureRequest#CONTROL_MODE
+     * @see #CONTROL_SCENE_MODE_DISABLED
+     * @see #CONTROL_SCENE_MODE_FACE_PRIORITY
+     * @see #CONTROL_SCENE_MODE_ACTION
+     * @see #CONTROL_SCENE_MODE_PORTRAIT
+     * @see #CONTROL_SCENE_MODE_LANDSCAPE
+     * @see #CONTROL_SCENE_MODE_NIGHT
+     * @see #CONTROL_SCENE_MODE_NIGHT_PORTRAIT
+     * @see #CONTROL_SCENE_MODE_THEATRE
+     * @see #CONTROL_SCENE_MODE_BEACH
+     * @see #CONTROL_SCENE_MODE_SNOW
+     * @see #CONTROL_SCENE_MODE_SUNSET
+     * @see #CONTROL_SCENE_MODE_STEADYPHOTO
+     * @see #CONTROL_SCENE_MODE_FIREWORKS
+     * @see #CONTROL_SCENE_MODE_SPORTS
+     * @see #CONTROL_SCENE_MODE_PARTY
+     * @see #CONTROL_SCENE_MODE_CANDLELIGHT
+     * @see #CONTROL_SCENE_MODE_BARCODE
+     */
+    public static final Key<Integer> CONTROL_SCENE_MODE =
+            new Key<Integer>("android.control.sceneMode", int.class);
+
+    /**
+     * <p>Whether video stabilization is
+     * active</p>
+     * <p>If enabled, video stabilization can modify the
+     * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to keep the video stream
+     * stabilized</p>
+     *
+     * @see CaptureRequest#SCALER_CROP_REGION
+     * @see #CONTROL_VIDEO_STABILIZATION_MODE_OFF
+     * @see #CONTROL_VIDEO_STABILIZATION_MODE_ON
+     */
+    public static final Key<Integer> CONTROL_VIDEO_STABILIZATION_MODE =
+            new Key<Integer>("android.control.videoStabilizationMode", int.class);
+
+    /**
      * <p>Operation mode for edge
      * enhancement.</p>
      * <p>Edge/sharpness/detail enhancement. OFF means no
@@ -1688,6 +1973,22 @@
             new Key<Float>("android.sensor.greenSplit", float.class);
 
     /**
+     * <p>A pixel <code>[R, G_even, G_odd, B]</code> that supplies the test pattern
+     * when {@link CaptureRequest#SENSOR_TEST_PATTERN_MODE android.sensor.testPatternMode} is SOLID_COLOR.</p>
+     * <p>Each color channel is treated as an unsigned 32-bit integer.
+     * The camera device then uses the most significant X bits
+     * that correspond to how many bits are in its Bayer raw sensor
+     * output.</p>
+     * <p>For example, a sensor with RAW10 Bayer output would use the
+     * 10 most significant bits from each color channel.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
+     */
+    public static final Key<int[]> SENSOR_TEST_PATTERN_DATA =
+            new Key<int[]>("android.sensor.testPatternData", int[].class);
+
+    /**
      * <p>When enabled, the sensor sends a test pattern instead of
      * doing a real exposure from the camera.</p>
      * <p>When a test pattern is enabled, all manual sensor controls specified
@@ -1936,6 +2237,20 @@
             new Key<int[]>("android.statistics.hotPixelMap", int[].class);
 
     /**
+     * <p>Whether the camera device will output the lens
+     * shading map in output result metadata.</p>
+     * <p>When set to ON,
+     * {@link CaptureResult#STATISTICS_LENS_SHADING_MAP android.statistics.lensShadingMap} must be provided in
+     * the output result metadata.</p>
+     *
+     * @see CaptureResult#STATISTICS_LENS_SHADING_MAP
+     * @see #STATISTICS_LENS_SHADING_MAP_MODE_OFF
+     * @see #STATISTICS_LENS_SHADING_MAP_MODE_ON
+     */
+    public static final Key<Integer> STATISTICS_LENS_SHADING_MAP_MODE =
+            new Key<Integer>("android.statistics.lensShadingMapMode", int.class);
+
+    /**
      * <p>Tonemapping / contrast / gamma curve for the blue
      * channel, to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is
      * CONTRAST_CURVE.</p>
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..2c224f6
--- /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 eafaed6..7213c78 100644
--- a/core/java/android/hardware/hdmi/HdmiCec.java
+++ b/core/java/android/hardware/hdmi/HdmiCec.java
@@ -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;
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 e6dbcd0..f6438b4 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -654,17 +654,20 @@
         return false;
     }
 
-    @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);
+    @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);
         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/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..e78ce33 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);
@@ -909,6 +911,8 @@
      */
     public abstract int getScreenOnCount(int which);
 
+    public abstract long getInteractiveTime(long elapsedRealtimeUs, int which);
+
     public static final int SCREEN_BRIGHTNESS_DARK = 0;
     public static final int SCREEN_BRIGHTNESS_DIM = 1;
     public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
@@ -934,8 +938,6 @@
     public abstract long getScreenBrightnessTime(int brightnessBin,
             long elapsedRealtimeUs, int which);
 
-    public abstract int getInputEventCount(int which);
-    
     /**
      * Returns the time in microseconds that the phone has been on while the device was
      * running on battery.
@@ -1569,6 +1571,7 @@
         final long totalRealtime = computeRealtime(rawRealtime, which);
         final long totalUptime = computeUptime(rawUptime, which);
         final long screenOnTime = getScreenOnTime(rawRealtime, which);
+        final long interactiveTime = getInteractiveTime(rawRealtime, which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
@@ -1637,8 +1640,8 @@
                 wifiRunningTime / 1000, bluetoothOnTime / 1000,
                 mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
                 fullWakeLockTimeTotal, partialWakeLockTimeTotal,
-                getInputEventCount(which), getMobileRadioActiveTime(rawRealtime, which),
-                getMobileRadioActiveAdjustedTime(which));
+                0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which),
+                getMobileRadioActiveAdjustedTime(which), interactiveTime / 1000);
         
         // Dump screen brightness stats
         Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
@@ -2011,6 +2014,7 @@
                 sb.append("realtime, ");
                 formatTimeMs(sb, totalUptime / 1000);
                 sb.append("uptime");
+        pw.println(sb.toString());
         if (batteryTimeRemaining >= 0) {
             sb.setLength(0);
             sb.append(prefix);
@@ -2029,16 +2033,25 @@
         pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
 
         final long screenOnTime = getScreenOnTime(rawRealtime, which);
+        final long interactiveTime = getInteractiveTime(rawRealtime, which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
         final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
         sb.setLength(0);
         sb.append(prefix);
+                sb.append("  Interactive: "); formatTimeMs(sb, interactiveTime / 1000);
+                sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
+                sb.append(")");
+        pw.println(sb.toString());
+        sb.setLength(0);
+        sb.append(prefix);
                 sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
                 sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
                 sb.append(") "); sb.append(getScreenOnCount(which));
-                sb.append("x, Input events: "); sb.append(getInputEventCount(which));
+                sb.append("x, Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
+                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
+                sb.append(")");
         pw.println(sb.toString());
         if (phoneOnTime != 0) {
             sb.setLength(0);
@@ -2897,7 +2910,7 @@
             }
         }
         if (!didWake && wakelockTag != null) {
-            pw.print(longNames ? "wake_lock=" : "w=");
+            pw.print(longNames ? " wake_lock=" : ",w=");
             if (longNames) {
                 UserHandle.formatUid(pw, wakelockTag.uid);
                 pw.print(":\"");
@@ -3076,7 +3089,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 +3436,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/provider/Settings.java b/core/java/android/provider/Settings.java
index ab06230..d5a3bcb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3480,6 +3480,12 @@
             "lock_screen_appwidget_ids";
 
         /**
+         * List of enrolled fingerprint identifiers (comma-delimited).
+         * @hide
+         */
+        public static final String USER_FINGERPRINT_IDS = "user_fingerprint_ids";
+
+        /**
          * Id of the appwidget shown on the lock screen when appwidgets are disabled.
          * @hide
          */
@@ -4395,6 +4401,13 @@
         public static final String ANR_SHOW_BACKGROUND = "anr_show_background";
 
         /**
+         * (Experimental). If nonzero, WebView uses data reduction proxy to save network
+         * bandwidth. Otherwise, WebView does not use data reduction proxy.
+         * @hide
+         */
+        public static final String WEBVIEW_DATA_REDUCTION_PROXY = "webview_data_reduction_proxy";
+
+        /**
          * The {@link ComponentName} string of the service to be used as the voice recognition
          * service.
          *
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 2303d65..b02a79d 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -300,10 +300,6 @@
     public void onDetachedFromWindow() {
     }
 
-    @Override
-    public void onWindowDismissed() {
-    }
-
     /** {@inheritDoc} */
     @Override
     public void onPanelClosed(int featureId, Menu menu) {
diff --git a/core/java/android/service/fingerprint/FingerprintManager.java b/core/java/android/service/fingerprint/FingerprintManager.java
new file mode 100644
index 0000000..0d14c59
--- /dev/null
+++ b/core/java/android/service/fingerprint/FingerprintManager.java
@@ -0,0 +1,200 @@
+/**
+ * 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.service.fingerprint;
+
+import android.app.ActivityManagerNative;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+/**
+ * A class that coordinates access to the fingerprint hardware.
+ */
+
+public class FingerprintManager {
+    private static final String TAG = "FingerprintManager";
+    protected static final boolean DEBUG = true;
+    private static final String FINGERPRINT_SERVICE_PACKAGE = "com.android.service.fingerprint";
+    private static final String FINGERPRINT_SERVICE_CLASS =
+            "com.android.service.fingerprint.FingerprintService";
+    private static final int MSG_ENROLL_RESULT = 100;
+    private static final int MSG_SCANNED = 101;
+    private static final int MSG_ERROR = 102;
+    private static final int MSG_REMOVED = 103;
+
+    public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10;
+    public static final int FINGERPRINT_ERROR = -1; // One of the error messages below.
+
+    // Progress messages.
+    public static final int FINGERPRINT_SCANNED = 1;
+    public static final int FINGERPRINT_TEMPLATE_ENROLLING = 2;
+    public static final int FINGERPRINT_TEMPLATE_REMOVED = 4;
+
+    // Error messages. Must agree with fingerprint HAL definitions.
+    public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
+    public static final int FINGERPRINT_ERROR_BAD_CAPTURE = 2;
+    public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
+    public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
+
+    private IFingerprintService mService;
+    private FingerprintManagerReceiver mClientReceiver;
+
+    private Handler mHandler = new Handler() {
+        public void handleMessage(android.os.Message msg) {
+            if (mClientReceiver != null) {
+                switch(msg.what) {
+                    case MSG_ENROLL_RESULT:
+                        mClientReceiver.onEnrollResult(msg.arg1, msg.arg2);
+                        break;
+                    case MSG_SCANNED:
+                        mClientReceiver.onScanned(msg.arg1, msg.arg2);
+                        break;
+                    case MSG_ERROR:
+                        mClientReceiver.onError(msg.arg1);
+                        break;
+                    case MSG_REMOVED:
+                        mClientReceiver.onRemoved(msg.arg1);
+                }
+            }
+        }
+    };
+
+    public FingerprintManager(Context context) {
+        // Connect to service...
+        Intent intent = new Intent();
+        intent.setClassName(FINGERPRINT_SERVICE_PACKAGE, FINGERPRINT_SERVICE_CLASS);
+        if (!context.bindServiceAsUser(intent, mFingerprintConnection,
+                Context.BIND_AUTO_CREATE, UserHandle.CURRENT_OR_SELF)) {
+            if (DEBUG) Log.v(TAG, "Can't bind to " + FINGERPRINT_SERVICE_CLASS);
+        }
+    }
+
+    private final ServiceConnection mFingerprintConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (DEBUG) Log.v(TAG, "Connected to FingerprintService");
+            mService = IFingerprintService.Stub.asInterface(service);
+            try {
+                mService.startListening(mServiceReceiver, getCurrentUserId());
+            } catch (RemoteException e) {
+                if (DEBUG) Log.v(TAG, "Failed to set callback", e);
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            if (DEBUG) Log.v(TAG, "Disconnected from FingerprintService");
+            mService = null;
+        }
+    };
+
+    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
+
+        public void onEnrollResult(int fingerprintId,  int remaining) {
+            mHandler.obtainMessage(MSG_ENROLL_RESULT, fingerprintId, remaining).sendToTarget();
+        }
+
+        public void onScanned(int fingerprintId, int confidence) {
+            mHandler.obtainMessage(MSG_SCANNED, fingerprintId, confidence)
+                    .sendToTarget();;
+        }
+
+        public void onError(int error) {
+            mHandler.obtainMessage(MSG_ERROR, error, 0).sendToTarget();
+        }
+
+        public void onRemoved(int fingerprintId) {
+            mHandler.obtainMessage(MSG_REMOVED, fingerprintId, 0).sendToTarget();
+        }
+    };
+
+    /**
+     * Start the enrollment process.  Timeout dictates how long to wait for the user to
+     * enroll a fingerprint.
+     *
+     * @param timeout
+     */
+    public void enroll(long timeout) {
+        if (mServiceReceiver == null) {
+            throw new IllegalStateException("enroll: Call registerCallback() first");
+        }
+        if (mService != null) try {
+            mService.enroll(timeout, getCurrentUserId());
+        } catch (RemoteException e) {
+            Log.v(TAG, "Remote exception while enrolling: ", e);
+        }
+    }
+
+    /**
+     * Remove the given fingerprintId from the system.  FingerprintId of 0 has special meaning
+     * which is to delete all fingerprint data for the current user. Use with caution.
+     * @param fingerprintId
+     */
+    public void remove(int fingerprintId) {
+        if (mService != null) try {
+            mService.remove(fingerprintId, getCurrentUserId());
+        } catch (RemoteException e) {
+            Log.v(TAG, "Remote exception during remove of fingerprintId: " + fingerprintId, e);
+        }
+    }
+
+    /**
+     * Starts listening for fingerprint events.  When a finger is scanned or recognized, the
+     * client will be notified via the callback.
+     */
+    public void startListening(FingerprintManagerReceiver receiver) {
+        mClientReceiver = receiver;
+        if (mService != null) {
+            try {
+                mService.startListening(mServiceReceiver, getCurrentUserId());
+            } catch (RemoteException e) {
+                Log.v(TAG, "Remote exception in startListening(): ", e);
+            }
+        }
+    }
+
+    private int getCurrentUserId() {
+        try {
+            return ActivityManagerNative.getDefault().getCurrentUser().id;
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to get current user id\n");
+            return UserHandle.USER_NULL;
+        }
+    }
+
+    /**
+     * Stops the client from listening to fingerprint events.
+     */
+    public void stopListening() {
+        mClientReceiver = null;
+        if (mService != null) {
+            try {
+                mService.stopListening(getCurrentUserId());
+            } catch (RemoteException e) {
+                Log.v(TAG, "Remote exception in stopListening(): ", e);
+            }
+        } else {
+            Log.w(TAG, "stopListening(): Service not connected!");
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java
new file mode 100644
index 0000000..34f1655
--- /dev/null
+++ b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java
@@ -0,0 +1,59 @@
+package android.service.fingerprint;
+/**
+ * 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.
+ */
+
+public class FingerprintManagerReceiver {
+    /**
+     * Fingerprint enrollment progress update. Enrollment is considered complete if
+     * remaining hits 0 without {@link #onError(int)} being called.
+     *
+     * @param fingerprintId the fingerprint we're currently enrolling
+     * @param remaining the number of samples required to complete enrollment. It's up to
+     * the hardware to define what each step in enrollment means. Some hardware
+     * requires multiple samples of the same part of the finger.  Others require sampling of
+     * different parts of the finger.  The enrollment flow can use remaining to
+     * mean "step x" of the process or "just need another sample."
+     */
+    public void onEnrollResult(int fingerprintId,  int remaining) { }
+
+    /**
+     * Fingerprint scan detected. Most clients will use this function to detect a fingerprint
+     *
+     * @param fingerprintId is the finger the hardware has detected.
+     * @param confidence from 0 (no confidence) to 65535 (high confidence). Fingerprint 0 has
+     * special meaning - the finger wasn't recognized.
+     */
+    public void onScanned(int fingerprintId, int confidence) { }
+
+    /**
+     * An error was detected during scan or enrollment.  One of
+     * {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE},
+     * {@link FingerprintManager#FINGERPRINT_ERROR_BAD_CAPTURE} or
+     * {@link FingerprintManager#FINGERPRINT_ERROR_TIMEOUT}
+     * {@link FingerprintManager#FINGERPRINT_ERROR_NO_SPACE}
+     *
+     * @param error one of the above error codes
+     */
+    public void onError(int error) { }
+
+    /**
+     * The given fingerprint template was successfully removed by the driver.
+     * See {@link FingerprintManager#remove(int)}
+     *
+     * @param fingerprintId id of template to remove.
+     */
+    public void onRemoved(int fingerprintId) { }
+}
\ No newline at end of file
diff --git a/core/java/android/service/fingerprint/FingerprintService.java b/core/java/android/service/fingerprint/FingerprintService.java
new file mode 100644
index 0000000..c7fa7cd
--- /dev/null
+++ b/core/java/android/service/fingerprint/FingerprintService.java
@@ -0,0 +1,219 @@
+/**
+ * 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.service.fingerprint;
+
+import android.app.Service;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+
+/**
+ * A service to manage multiple clients that want to access the fingerprint HAL API.
+ * The service is responsible for maintaining a list of clients and dispatching all
+ * fingerprint -related events.
+ *
+ * @hide
+ */
+public class FingerprintService extends Service {
+    private final String TAG = FingerprintService.class.getSimpleName() +
+            "[" + getClass().getSimpleName() + "]";
+    private static final boolean DEBUG = true;
+    HashMap<IFingerprintServiceReceiver, ClientData> mClients =
+            new HashMap<IFingerprintServiceReceiver, ClientData>();
+
+    private static final int MSG_NOTIFY = 10;
+
+    Handler mHandler = new Handler() {
+        public void handleMessage(android.os.Message msg) {
+            switch (msg.what) {
+                case MSG_NOTIFY:
+                    handleNotify(msg.arg1, msg.arg2, (Integer) msg.obj);
+                    break;
+
+                default:
+                    Slog.w(TAG, "Unknown message:" + msg.what);
+            }
+        }
+    };
+
+    private static final int STATE_IDLE = 0;
+    private static final int STATE_LISTENING = 1;
+    private static final int STATE_ENROLLING = 2;
+    private static final int STATE_DELETING = 3;
+    private static final long MS_PER_SEC = 1000;
+
+    private static final class ClientData {
+        public IFingerprintServiceReceiver receiver;
+        int state;
+        int userId;
+    }
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
+        return new FingerprintServiceWrapper();
+    }
+
+    // JNI methods to communicate from FingerprintManagerService to HAL
+    native int nativeEnroll(int timeout);
+    native int nativeRemove(int fingerprintId);
+
+    // JNI methods for communicating from HAL to clients
+    void notify(int msg, int arg1, int arg2) {
+        mHandler.obtainMessage(MSG_NOTIFY, msg, arg1, arg2).sendToTarget();
+    }
+
+    void handleNotify(int msg, int arg1, int arg2) {
+        for (int i = 0; i < mClients.size(); i++) {
+            ClientData clientData = mClients.get(i);
+            switch (msg) {
+                case FingerprintManager.FINGERPRINT_ERROR: {
+                    if (clientData.state != STATE_IDLE) {
+                        // FINGERPRINT_ERROR_HW_UNAVAILABLE
+                        // FINGERPRINT_ERROR_BAD_CAPTURE
+                        // FINGERPRINT_ERROR_TIMEOUT
+                        // FINGERPRINT_ERROR_NO_SPACE
+                        final int error = arg1;
+                        clientData.state = STATE_IDLE;
+                        if (clientData.receiver != null) {
+                            try {
+                                clientData.receiver.onError(error);
+                            } catch (RemoteException e) {
+                                Slog.e(TAG, "can't send message to client. Did it die?", e);
+                            }
+                        }
+                    }
+                }
+                break;
+                case FingerprintManager.FINGERPRINT_SCANNED: {
+                    final int fingerId = arg1;
+                    final int confidence = arg2;
+                    if (clientData.state == STATE_LISTENING && clientData.receiver != null) {
+                        try {
+                            clientData.receiver.onScanned(fingerId, confidence);
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "can't send message to client. Did it die?", e);
+                        }
+                    }
+                    break;
+                }
+                case FingerprintManager.FINGERPRINT_TEMPLATE_ENROLLING: {
+                    if (clientData.state == STATE_ENROLLING) {
+                        final int fingerId = arg1;
+                        final int remaining = arg2;
+                        if (remaining == 0) {
+                            FingerprintUtils.addFingerprintIdForUser(fingerId,
+                                    getContentResolver(), clientData.userId);
+                            clientData.state = STATE_IDLE; // Nothing left to do
+                        }
+                        if (clientData.receiver != null) {
+                            try {
+                                clientData.receiver.onEnrollResult(fingerId, remaining);
+                            } catch (RemoteException e) {
+                                Slog.e(TAG, "can't send message to client. Did it die?", e);
+                            }
+                        }
+                    }
+                    break;
+                }
+                case FingerprintManager.FINGERPRINT_TEMPLATE_REMOVED: {
+                    int fingerId = arg1;
+                    if (fingerId == 0) throw new IllegalStateException("Got illegal id from HAL");
+                    if (clientData.state == STATE_DELETING) {
+                        FingerprintUtils.removeFingerprintIdForUser(fingerId, getContentResolver(),
+                                clientData.userId);
+                        if (clientData.receiver != null) {
+                            try {
+                                clientData.receiver.onRemoved(fingerId);
+                            } catch (RemoteException e) {
+                                Slog.e(TAG, "can't send message to client. Did it die?", e);
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    int enroll(IFingerprintServiceReceiver receiver, long timeout, int userId) {
+        ClientData clientData = mClients.get(receiver);
+        if (clientData != null) {
+            if (clientData.userId != userId) throw new IllegalStateException("Bad user");
+            clientData.state = STATE_ENROLLING;
+            return nativeEnroll((int) (timeout / MS_PER_SEC));
+        }
+        return -1;
+    }
+
+    int remove(IFingerprintServiceReceiver receiver, int fingerId, int userId) {
+        ClientData clientData = mClients.get(receiver);
+        if (clientData != null) {
+            if (clientData.userId != userId) throw new IllegalStateException("Bad user");
+            clientData.state = STATE_DELETING;
+            // The fingerprint id will be removed when we get confirmation from the HAL
+            return nativeRemove(fingerId);
+        }
+        return -1;
+    }
+
+    void startListening(IFingerprintServiceReceiver receiver, int userId) {
+        ClientData clientData = new ClientData();
+        clientData.state = STATE_LISTENING;
+        clientData.receiver = receiver;
+        clientData.userId = userId;
+        mClients.put(receiver, clientData);
+    }
+
+    void stopListening(IFingerprintServiceReceiver receiver, int userId) {
+        ClientData clientData = mClients.get(receiver);
+        if (clientData != null) {
+            clientData.state = STATE_IDLE;
+            clientData.userId = -1;
+            clientData.receiver = null;
+        }
+        mClients.remove(receiver);
+    }
+
+    private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
+        IFingerprintServiceReceiver mReceiver;
+        public int enroll(long timeout, int userId) {
+            return mReceiver != null ? FingerprintService.this.enroll(mReceiver, timeout, userId)
+                    : FingerprintManager.FINGERPRINT_ERROR_NO_RECEIVER;
+        }
+
+        public int remove(int fingerprintId, int userId) {
+            return FingerprintService.this.remove(mReceiver, fingerprintId, userId);
+        }
+
+        public void startListening(IFingerprintServiceReceiver receiver, int userId) {
+            mReceiver = receiver;
+            FingerprintService.this.startListening(receiver, userId);
+        }
+
+        public void stopListening(int userId) {
+            FingerprintService.this.stopListening(mReceiver, userId);
+        }
+    }
+}
diff --git a/core/java/android/service/fingerprint/FingerprintUtils.java b/core/java/android/service/fingerprint/FingerprintUtils.java
new file mode 100644
index 0000000..81a2aac
--- /dev/null
+++ b/core/java/android/service/fingerprint/FingerprintUtils.java
@@ -0,0 +1,85 @@
+/**
+ * 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.service.fingerprint;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.Arrays;
+
+class FingerprintUtils {
+    private static final boolean DEBUG = true;
+    private static final String TAG = "FingerprintUtils";
+
+    public static int[] getFingerprintIdsForUser(ContentResolver res, int userId) {
+        String fingerIdsRaw = Settings.Secure.getStringForUser(res,
+                Settings.Secure.USER_FINGERPRINT_IDS, userId);
+
+        String[] fingerStringIds = fingerIdsRaw.replace("[","").replace("]","").split(", ");
+        int result[] = new int[fingerStringIds.length];
+        for (int i = 0; i < result.length; i++) {
+            try {
+                result[i] = Integer.decode(fingerStringIds[i]);
+            } catch (NumberFormatException e) {
+                if (DEBUG) Log.d(TAG, "Error when parsing finger id " + fingerStringIds[i]);
+            }
+        }
+        return result;
+    }
+
+    public static void addFingerprintIdForUser(int fingerId, ContentResolver res, int userId) {
+        int[] fingerIds = getFingerprintIdsForUser(res, userId);
+
+        // FingerId 0 has special meaning.
+        if (fingerId == 0) return;
+
+        // Don't allow dups
+        for (int i = 0; i < fingerIds.length; i++) {
+            if (fingerIds[i] == fingerId) return;
+        }
+        int[] newList = Arrays.copyOf(fingerIds, fingerIds.length + 1);
+        newList[fingerIds.length] = fingerId;
+        Settings.Secure.putStringForUser(res, Settings.Secure.USER_FINGERPRINT_IDS,
+                Arrays.toString(newList), userId);
+    }
+
+    public static boolean removeFingerprintIdForUser(int fingerId, ContentResolver res, int userId)
+    {
+        // FingerId 0 has special meaning. The HAL layer is supposed to remove each finger one
+        // at a time and invoke notify() for each fingerId.  If we get called with 0 here, it means
+        // something bad has happened.
+        if (fingerId == 0) throw new IllegalStateException("Bad fingerId");
+
+        int[] fingerIds = getFingerprintIdsForUser(res, userId);
+        int[] resultIds = Arrays.copyOf(fingerIds, fingerIds.length);
+        int resultCount = 0;
+        for (int i = 0; i < fingerIds.length; i++) {
+            if (fingerId != fingerIds[i]) {
+                resultIds[resultCount++] = fingerIds[i];
+            }
+        }
+        if (resultCount > 0) {
+            Settings.Secure.putStringForUser(res, Settings.Secure.USER_FINGERPRINT_IDS,
+                    Arrays.toString(Arrays.copyOf(resultIds, resultCount)), userId);
+            return true;
+        }
+        return false;
+    }
+
+};
+
diff --git a/core/java/android/service/fingerprint/IFingerprintService.aidl b/core/java/android/service/fingerprint/IFingerprintService.aidl
new file mode 100644
index 0000000..e92c20c
--- /dev/null
+++ b/core/java/android/service/fingerprint/IFingerprintService.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.service.fingerprint;
+
+import android.os.Bundle;
+import android.service.fingerprint.IFingerprintServiceReceiver;
+
+/**
+ * Communication channel from client to the fingerprint service.
+ * @hide
+ */
+interface IFingerprintService {
+    // Returns 0 if successfully started, -1 otherwise
+    int enroll(long timeout, int userId);
+
+    // Returns 0 if fingerprintId's template can be removed, -1 otherwise
+    int remove(int fingerprintId, int userId);
+
+    // Start listening for fingerprint events.  This has the side effect of starting
+    // the hardware if not already started.
+    oneway void startListening(IFingerprintServiceReceiver receiver, int userId);
+
+    // Stops listening for fingerprints
+    oneway void stopListening(int userId);
+}
diff --git a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl
new file mode 100644
index 0000000..4826b59
--- /dev/null
+++ b/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.service.fingerprint;
+
+import android.os.Bundle;
+import android.os.UserHandle;
+
+/**
+ * Communication channel from the FingerprintService back to FingerprintManager.
+ * @hide
+ */
+oneway interface IFingerprintServiceReceiver {
+    void onEnrollResult(int fingerprintId,  int remaining);
+    void onScanned(int fingerprintId, int confidence);
+    void onError(int error);
+    void onRemoved(int fingerprintId);
+}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 72720d1..e7cdc4e 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -87,7 +87,7 @@
     }
 
     private String key() {
-        return pkg + '|' + id + '|' + tag + '|' + uid;
+        return user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid;
     }
 
     public void writeToParcel(Parcel out, int flags) {
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/speech/tts/BlockingAudioTrack.java b/core/java/android/speech/tts/BlockingAudioTrack.java
index 186cb49..92bb0ac 100644
--- a/core/java/android/speech/tts/BlockingAudioTrack.java
+++ b/core/java/android/speech/tts/BlockingAudioTrack.java
@@ -83,7 +83,7 @@
         mVolume = volume;
         mPan = pan;
 
-        mBytesPerFrame = getBytesPerFrame(mAudioFormat) * mChannelCount;
+        mBytesPerFrame = AudioFormat.getBytesPerSample(mAudioFormat) * mChannelCount;
         mIsShortUtterance = false;
         mAudioBufferSize = 0;
         mBytesWritten = 0;
@@ -229,17 +229,6 @@
         return audioTrack;
     }
 
-    private static int getBytesPerFrame(int audioFormat) {
-        if (audioFormat == AudioFormat.ENCODING_PCM_8BIT) {
-            return 1;
-        } else if (audioFormat == AudioFormat.ENCODING_PCM_16BIT) {
-            return 2;
-        }
-
-        return -1;
-    }
-
-
     private void blockUntilDone(AudioTrack audioTrack) {
         if (mBytesWritten <= 0) {
             return;
diff --git a/core/java/android/speech/tts/FileSynthesisCallback.java b/core/java/android/speech/tts/FileSynthesisCallback.java
index 717aeb6..d84f7f0 100644
--- a/core/java/android/speech/tts/FileSynthesisCallback.java
+++ b/core/java/android/speech/tts/FileSynthesisCallback.java
@@ -278,8 +278,7 @@
 
     private ByteBuffer makeWavHeader(int sampleRateInHz, int audioFormat, int channelCount,
             int dataLength) {
-        // TODO: is AudioFormat.ENCODING_DEFAULT always the same as ENCODING_PCM_16BIT?
-        int sampleSizeInBytes = (audioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
+        int sampleSizeInBytes = AudioFormat.getBytesPerSample(audioFormat);
         int byteRate = sampleRateInHz * sampleSizeInBytes * channelCount;
         short blockAlign = (short) (sampleSizeInBytes * channelCount);
         short bitsPerSample = (short) (sampleSizeInBytes * 8);
diff --git a/core/java/android/transition/MoveImage.java b/core/java/android/transition/MoveImage.java
index e4c3939..183cdd2 100644
--- a/core/java/android/transition/MoveImage.java
+++ b/core/java/android/transition/MoveImage.java
@@ -125,7 +125,7 @@
         Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
         Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
 
-        if (!startMatrix.equals(endMatrix)) {
+        if (startMatrix != null && !startMatrix.equals(endMatrix)) {
             changes.add(PropertyValuesHolder.ofObject(MatrixClippedDrawable.MATRIX_PROPERTY,
                     new MatrixEvaluator(), startMatrix, endMatrix));
         }
@@ -230,7 +230,9 @@
 
     private static void expandClip(Rect bounds, Matrix matrix, Rect clip, Rect otherClip) {
         RectF boundsF = new RectF(bounds);
-        matrix.mapRect(boundsF);
+        if (matrix != null) {
+            matrix.mapRect(boundsF);
+        }
         clip.left = expandMinDimension(boundsF.left, clip.left, otherClip.left);
         clip.top = expandMinDimension(boundsF.top, clip.top, otherClip.top);
         clip.right = expandMaxDimension(boundsF.right, clip.right, otherClip.right);
@@ -256,10 +258,20 @@
         int drawableWidth = drawable.getIntrinsicWidth();
         int drawableHeight = drawable.getIntrinsicHeight();
         ImageView.ScaleType scaleType = imageView.getScaleType();
-        if (drawableWidth <= 0 || drawableHeight <= 0 || scaleType == ImageView.ScaleType.FIT_XY) {
-            return null;
+        Matrix matrix;
+        if (drawableWidth <= 0 || drawableHeight <= 0) {
+            matrix = null;
+        } else if (scaleType == ImageView.ScaleType.FIT_XY) {
+            matrix = new Matrix();
+            float scaleX = imageView.getWidth();
+            scaleX /= drawableWidth;
+            float scaleY = imageView.getHeight();
+            scaleY /= drawableHeight;
+            matrix.setScale(scaleX, scaleY);
+        } else {
+            matrix = new Matrix(imageView.getImageMatrix());
         }
-        return new Matrix(imageView.getImageMatrix());
+        return matrix;
     }
 
     private Rect findClip(ImageView imageView) {
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/Choreographer.java b/core/java/android/view/Choreographer.java
index f1523ae..0a76075 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -259,6 +259,14 @@
         return delayMillis <= frameDelay ? 0 : delayMillis - frameDelay;
     }
 
+    /**
+     * @return The refresh rate as the nanoseconds between frames
+     * @hide
+     */
+    long getFrameIntervalNanos() {
+        return mFrameIntervalNanos;
+    }
+
     void dump(String prefix, PrintWriter writer) {
         String innerPrefix = prefix + "  ";
         writer.print(prefix); writer.println("Choreographer:");
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index ba1c4b6..0afbde9 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -96,7 +96,7 @@
             return mTheme;
         }
 
-        mThemeResource = getResources().selectDefaultTheme(mThemeResource,
+        mThemeResource = Resources.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/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/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 2d55a01..c15ce44 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -74,8 +74,10 @@
             IBinder displayToken, int orientation,
             int l, int t, int r, int b,
             int L, int T, int R, int B);
-    private static native boolean nativeGetDisplayInfo(
-            IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo);
+    private static native SurfaceControl.PhysicalDisplayInfo[] nativeGetDisplayConfigs(
+            IBinder displayToken);
+    private static native int nativeGetActiveConfig(IBinder displayToken);
+    private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
     private static native void nativeBlankDisplay(IBinder displayToken);
     private static native void nativeUnblankDisplay(IBinder displayToken);
 
@@ -499,14 +501,25 @@
         nativeBlankDisplay(displayToken);
     }
 
-    public static boolean getDisplayInfo(IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo) {
+    public static SurfaceControl.PhysicalDisplayInfo[] getDisplayConfigs(IBinder displayToken) {
         if (displayToken == null) {
             throw new IllegalArgumentException("displayToken must not be null");
         }
-        if (outInfo == null) {
-            throw new IllegalArgumentException("outInfo must not be null");
+        return nativeGetDisplayConfigs(displayToken);
+    }
+
+    public static int getActiveConfig(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
         }
-        return nativeGetDisplayInfo(displayToken, outInfo);
+        return nativeGetActiveConfig(displayToken);
+    }
+
+    public static boolean setActiveConfig(IBinder displayToken, int id) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        return nativeSetActiveConfig(displayToken, id);
     }
 
     public static void setDisplayProjection(IBinder displayToken,
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 3cfe5e9..1765c43 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -23,7 +23,6 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
-import android.os.Looper;
 import android.util.AttributeSet;
 import android.util.Log;
 
@@ -119,8 +118,6 @@
     private boolean mUpdateLayer;
     private boolean mUpdateSurface;
 
-    private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
-
     private Canvas mCanvas;
     private int mSaveCount;
 
@@ -370,21 +367,7 @@
             mSurface.setDefaultBufferSize(getWidth(), getHeight());
             nCreateNativeWindow(mSurface);
 
-            mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() {
-                @Override
-                public void onFrameAvailable(SurfaceTexture surfaceTexture) {
-                    // Per SurfaceTexture's documentation, the callback may be invoked
-                    // from an arbitrary thread
-                    updateLayer();
-
-                    if (Looper.myLooper() == Looper.getMainLooper()) {
-                        invalidate();
-                    } else {
-                        postInvalidate();
-                    }
-                }
-            };
-            mSurface.setOnFrameAvailableListener(mUpdateListener);
+            mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
 
             if (mListener != null && !mUpdateSurface) {
                 mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
@@ -422,7 +405,7 @@
             // To cancel updates, the easiest thing to do is simply to remove the
             // updates listener
             if (visibility == VISIBLE) {
-                mSurface.setOnFrameAvailableListener(mUpdateListener);
+                mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
                 updateLayerAndInvalidate();
             } else {
                 mSurface.setOnFrameAvailableListener(null);
@@ -767,6 +750,15 @@
         mListener = listener;
     }
 
+    private final SurfaceTexture.OnFrameAvailableListener mUpdateListener =
+            new SurfaceTexture.OnFrameAvailableListener() {
+        @Override
+        public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+            updateLayer();
+            invalidate();
+        }
+    };
+
     /**
      * This listener can be used to be notified when the surface texture
      * associated with this texture view is available.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index eaec8ab..0bf99d3 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -19,7 +19,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
-import android.os.SystemClock;
 import android.os.Trace;
 import android.view.Surface.OutOfResourcesException;
 import android.view.View.AttachInfo;
@@ -52,16 +51,29 @@
 
     private static final Rect NULL_RECT = new Rect();
 
+    private static final long NANOS_PER_MS = 1000000;
+
+    // Keep in sync with DrawFrameTask.h SYNC_* flags
+    // Nothing interesting to report
+    private static final int SYNC_OK = 0x0;
+    // Needs a ViewRoot invalidate
+    private static final int SYNC_INVALIDATE_REQUIRED = 0x1;
+
     private int mWidth, mHeight;
     private long mNativeProxy;
     private boolean mInitialized = false;
     private RenderNode mRootNode;
+    private Choreographer mChoreographer;
 
     ThreadedRenderer(boolean translucent) {
         long rootNodePtr = nCreateRootRenderNode();
         mRootNode = RenderNode.adopt(rootNodePtr);
         mRootNode.setClipToBounds(false);
         mNativeProxy = nCreateProxy(translucent, rootNodePtr);
+
+        // Setup timing
+        mChoreographer = Choreographer.getInstance();
+        nSetFrameInterval(mNativeProxy, mChoreographer.getFrameIntervalNanos());
     }
 
     @Override
@@ -158,16 +170,7 @@
 
     @Override
     boolean loadSystemProperties() {
-        return false;
-    }
-
-    /**
-     * TODO: Remove
-     * Temporary hack to allow RenderThreadTest prototype app to trigger
-     * replaying a DisplayList after modifying the displaylist properties
-     *
-     *  @hide */
-    public void repeatLastDraw() {
+        return nLoadSystemProperties(mNativeProxy);
     }
 
     private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
@@ -194,7 +197,8 @@
     @Override
     void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
         attachInfo.mIgnoreDirtyState = true;
-        attachInfo.mDrawingTime = SystemClock.uptimeMillis();
+        long frameTimeNanos = mChoreographer.getFrameTimeNanos();
+        attachInfo.mDrawingTime = frameTimeNanos / NANOS_PER_MS;
 
         updateRootDisplayList(view, callbacks);
 
@@ -203,7 +207,11 @@
         if (dirty == null) {
             dirty = NULL_RECT;
         }
-        nSyncAndDrawFrame(mNativeProxy, dirty.left, dirty.top, dirty.right, dirty.bottom);
+        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
+                dirty.left, dirty.top, dirty.right, dirty.bottom);
+        if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
+            attachInfo.mViewRootImpl.invalidate();
+        }
     }
 
     @Override
@@ -297,13 +305,16 @@
     private static native long nCreateProxy(boolean translucent, long rootRenderNode);
     private static native void nDeleteProxy(long nativeProxy);
 
+    private static native void nSetFrameInterval(long nativeProxy, long frameIntervalNanos);
+    private static native boolean nLoadSystemProperties(long nativeProxy);
+
     private static native boolean nInitialize(long nativeProxy, Surface window);
     private static native void nUpdateSurface(long nativeProxy, Surface window);
     private static native void nPauseSurface(long nativeProxy, Surface window);
     private static native void nSetup(long nativeProxy, int width, int height);
     private static native void nSetDisplayListData(long nativeProxy, long displayList,
             long newData);
-    private static native void nSyncAndDrawFrame(long nativeProxy,
+    private static native int nSyncAndDrawFrame(long nativeProxy, long frameTimeNanos,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
     private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
     private static native void nDestroyCanvasAndSurface(long nativeProxy);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6afff4d..69840c4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6147,12 +6147,12 @@
             // call into it as a fallback in case we're in a class that overrides it
             // and has logic to perform.
             if (fitSystemWindows(insets.getSystemWindowInsets())) {
-                return insets.cloneWithSystemWindowInsetsConsumed();
+                return insets.consumeSystemWindowInsets();
             }
         } else {
             // We were called from within a direct call to fitSystemWindows.
             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
-                return insets.cloneWithSystemWindowInsetsConsumed();
+                return insets.consumeSystemWindowInsets();
             }
         }
         return insets;
@@ -9958,7 +9958,7 @@
      * @attr ref android.R.styleable#View_transformPivotX
      */
     public void setPivotX(float pivotX) {
-        if (mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
+        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
             invalidateViewProperty(true, false);
             mRenderNode.setPivotX(pivotX);
             invalidateViewProperty(false, true);
@@ -9999,7 +9999,7 @@
      * @attr ref android.R.styleable#View_transformPivotY
      */
     public void setPivotY(float pivotY) {
-        if (mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
+        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
             invalidateViewProperty(true, false);
             mRenderNode.setPivotY(pivotY);
             invalidateViewProperty(false, true);
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 48a5bd5..4e91ad4 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;
     }
 
     /**
@@ -342,6 +344,8 @@
                 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);
     }
 
     /**
@@ -698,12 +702,26 @@
      *
      * @return how long a user needs to press the relevant key to bring up
      *   the global actions dialog.
+     * @deprecated This timeout should not be used by applications
      */
+    @Deprecated
     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.
+     * @hide
+     */
+    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/Window.java b/core/java/android/view/Window.java
index 9c44bd1..375f5e3 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -147,6 +147,7 @@
     
     private TypedArray mWindowStyle;
     private Callback mCallback;
+    private OnWindowDismissedCallback mOnWindowDismissedCallback;
     private WindowManager mWindowManager;
     private IBinder mAppToken;
     private String mAppName;
@@ -405,7 +406,10 @@
          * @param mode The mode that was just finished.
          */
         public void onActionModeFinished(ActionMode mode);
+    }
 
+    /** @hide */
+    public interface OnWindowDismissedCallback {
         /**
          * Called when a window is dismissed. This informs the callback that the
          * window is gone, and it should finish itself.
@@ -586,6 +590,18 @@
         return mCallback;
     }
 
+    /** @hide */
+    public final void setOnWindowDismissedCallback(OnWindowDismissedCallback dcb) {
+        mOnWindowDismissedCallback = dcb;
+    }
+
+    /** @hide */
+    public final void dispatchOnWindowDismissed() {
+        if (mOnWindowDismissedCallback != null) {
+            mOnWindowDismissedCallback.onWindowDismissed();
+        }
+    }
+
     /**
      * Take ownership of this window's surface.  The window's view hierarchy
      * will no longer draw into the surface, though it will otherwise continue
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 2160efe..294f472 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -29,7 +29,7 @@
  * @see View.OnApplyWindowInsetsListener
  * @see View#onApplyWindowInsets(WindowInsets)
  */
-public class WindowInsets {
+public final class WindowInsets {
     private Rect mSystemWindowInsets;
     private Rect mWindowDecorInsets;
     private Rect mTempRect;
@@ -151,6 +151,7 @@
      * This can include action bars, title bars, toolbars, etc.</p>
      *
      * @return The left window decor inset
+     * @hide pending API
      */
     public int getWindowDecorInsetLeft() {
         return mWindowDecorInsets.left;
@@ -164,6 +165,7 @@
      * This can include action bars, title bars, toolbars, etc.</p>
      *
      * @return The top window decor inset
+     * @hide pending API
      */
     public int getWindowDecorInsetTop() {
         return mWindowDecorInsets.top;
@@ -177,6 +179,7 @@
      * This can include action bars, title bars, toolbars, etc.</p>
      *
      * @return The right window decor inset
+     * @hide pending API
      */
     public int getWindowDecorInsetRight() {
         return mWindowDecorInsets.right;
@@ -190,6 +193,7 @@
      * This can include action bars, title bars, toolbars, etc.</p>
      *
      * @return The bottom window decor inset
+     * @hide pending API
      */
     public int getWindowDecorInsetBottom() {
         return mWindowDecorInsets.bottom;
@@ -217,6 +221,7 @@
      * This can include action bars, title bars, toolbars, etc.</p>
      *
      * @return true if any of the window decor inset values are nonzero
+     * @hide pending API
      */
     public boolean hasWindowDecorInsets() {
         return mWindowDecorInsets.left != 0 || mWindowDecorInsets.top != 0 ||
@@ -246,13 +251,28 @@
         return mIsRound;
     }
 
-    public WindowInsets cloneWithSystemWindowInsetsConsumed() {
+    /**
+     * Returns a copy of this WindowInsets with the system window insets fully consumed.
+     *
+     * @return A modified copy of this WindowInsets
+     */
+    public WindowInsets consumeSystemWindowInsets() {
         final WindowInsets result = new WindowInsets(this);
         result.mSystemWindowInsets = new Rect(0, 0, 0, 0);
         return result;
     }
 
-    public WindowInsets cloneWithSystemWindowInsetsConsumed(boolean left, boolean top,
+    /**
+     * Returns a copy of this WindowInsets with selected system window insets fully consumed.
+     *
+     * @param left true to consume the left system window inset
+     * @param top true to consume the top system window inset
+     * @param right true to consume the right system window inset
+     * @param bottom true to consume the bottom system window inset
+     * @return A modified copy of this WindowInsets
+     * @hide pending API
+     */
+    public WindowInsets consumeSystemWindowInsets(boolean left, boolean top,
             boolean right, boolean bottom) {
         if (left || top || right || bottom) {
             final WindowInsets result = new WindowInsets(this);
@@ -265,19 +285,36 @@
         return this;
     }
 
-    public WindowInsets cloneWithSystemWindowInsets(int left, int top, int right, int bottom) {
+    /**
+     * Returns a copy of this WindowInsets with selected system window insets replaced
+     * with new values.
+     *
+     * @param left New left inset in pixels
+     * @param top New top inset in pixels
+     * @param right New right inset in pixels
+     * @param bottom New bottom inset in pixels
+     * @return A modified copy of this WindowInsets
+     */
+    public WindowInsets replaceSystemWindowInsets(int left, int top,
+            int right, int bottom) {
         final WindowInsets result = new WindowInsets(this);
         result.mSystemWindowInsets = new Rect(left, top, right, bottom);
         return result;
     }
 
-    public WindowInsets cloneWithWindowDecorInsetsConsumed() {
+    /**
+     * @hide
+     */
+    public WindowInsets consumeWindowDecorInsets() {
         final WindowInsets result = new WindowInsets(this);
         result.mWindowDecorInsets.set(0, 0, 0, 0);
         return result;
     }
 
-    public WindowInsets cloneWithWindowDecorInsetsConsumed(boolean left, boolean top,
+    /**
+     * @hide
+     */
+    public WindowInsets consumeWindowDecorInsets(boolean left, boolean top,
             boolean right, boolean bottom) {
         if (left || top || right || bottom) {
             final WindowInsets result = new WindowInsets(this);
@@ -290,7 +327,10 @@
         return this;
     }
 
-    public WindowInsets cloneWithWindowDecorInsets(int left, int top, int right, int bottom) {
+    /**
+     * @hide
+     */
+    public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) {
         final WindowInsets result = new WindowInsets(this);
         result.mWindowDecorInsets = new Rect(left, top, right, bottom);
         return result;
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/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java
index 2f8850b..3e33498 100644
--- a/core/java/android/webkit/PermissionRequest.java
+++ b/core/java/android/webkit/PermissionRequest.java
@@ -19,14 +19,11 @@
 import android.net.Uri;
 
 /**
- * This class wraps a permission request, and is used to request permission for
- * the web content to access the resources.
+ * This interface defines a permission request and is used when web content
+ * requests access to protected resources.
  *
- * Either {@link #grant(long) grant()} or {@link #deny()} must be called to response the
- * request, otherwise, {@link WebChromeClient#onPermissionRequest(PermissionRequest)} will
- * not be invoked again if there is other permission request in this WebView.
- *
- * @hide
+ * Either {@link #grant(long) grant()} or {@link #deny()} must be called in UI
+ * thread to respond to the request.
  */
 public interface PermissionRequest {
     /**
@@ -62,8 +59,6 @@
      *        must be equals or a subset of granted resources.
      *        This parameter is designed to avoid granting permission by accident
      *        especially when new resources are requested by web content.
-     *        Calling grant(getResources()) has security issue, the new permission
-     *        will be granted without being noticed.
      */
     public void grant(long resources);
 
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 60cba86..d630a9a 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -304,7 +304,6 @@
      * If this method isn't overridden, the permission is denied.
      *
      * @param request the PermissionRequest from current web content.
-     * @hide
      */
     public void onPermissionRequest(PermissionRequest request) {
         request.deny();
@@ -314,8 +313,7 @@
      * Notify the host application that the given permission request
      * has been canceled. Any related UI should therefore be hidden.
      *
-     * @param request the PermissionRequest need be canceled.
-     * @hide
+     * @param request the PermissionRequest that needs be canceled.
      */
     public void onPermissionRequestCanceled(PermissionRequest request) {}
 
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 efb246a..91ca7b4 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;
@@ -250,6 +251,15 @@
         implements ViewTreeObserver.OnGlobalFocusChangeListener,
         ViewGroup.OnHierarchyChangeListener, ViewDebug.HierarchyHandler {
 
+    /**
+     * Broadcast Action: Indicates the data reduction proxy setting changed.
+     * Sent by the settings app when user changes the data reduction proxy value. This intent will
+     * always stay as a hidden API.
+     * @hide
+     */
+    public static final String DATA_REDUCTION_PROXY_SETTING_CHANGED =
+            "android.webkit.DATA_REDUCTION_PROXY_SETTING_CHANGED";
+
     private static final String LOGTAG = "WebView";
 
     // Throwing an exception for incorrect thread usage if the
@@ -1479,18 +1489,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);
     }
 
     /**
@@ -1674,13 +1682,15 @@
 
     /**
      * Preauthorize the given origin to access resources.
-     * This authorization only valid for this WebView instance life cycle and
+     * The authorization only valid for this WebView instance's life cycle and
      * will not retained.
      *
+     * In the case that an origin has had resources preauthorized, calls to
+     * {@link WebChromeClient#onPermissionRequest(PermissionRequest)} will not be
+     * made for those resources from that origin.
+     *
      * @param origin the origin authorized to access resources
      * @param resources the resource authorized to be accessed by origin.
-     *
-     * @hide
      */
     public void preauthorizePermission(Uri origin, long resources) {
         checkThread();
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 33a6df6..62b80c4a 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -224,8 +224,6 @@
      * @param view The WebView that is initiating the callback
      * @param request An instance of a {@link ClientCertRequest}
      *
-     * TODO(sgurun) unhide
-     * @hide
      */
     public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
         request.cancel();
@@ -287,11 +285,12 @@
      * 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 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.
+     * 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}
+     * 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.
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 0966be3..f4cd5fc 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -611,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;
@@ -3264,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;
@@ -3292,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) {
@@ -3361,39 +3376,48 @@
 
                         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];
+                            if (vtev != null) {
+                                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) {
@@ -3517,6 +3541,8 @@
             return false;
         }
 
+        startNestedScroll(SCROLL_AXIS_VERTICAL);
+
         if (mFastScroll != null) {
             boolean intercepted = mFastScroll.onTouchEvent(ev);
             if (intercepted) {
@@ -3525,7 +3551,7 @@
         }
 
         initVelocityTrackerIfNotExists();
-        mVelocityTracker.addMovement(ev);
+        final MotionEvent vtev = MotionEvent.obtain(ev);
 
         final int actionMasked = ev.getActionMasked();
         switch (actionMasked) {
@@ -3535,7 +3561,7 @@
             }
 
             case MotionEvent.ACTION_MOVE: {
-                onTouchMove(ev);
+                onTouchMove(ev, vtev);
                 break;
             }
 
@@ -3586,6 +3612,10 @@
             }
         }
 
+        if (mVelocityTracker != null) {
+            mVelocityTracker.addMovement(vtev);
+        }
+        vtev.recycle();
         return true;
     }
 
@@ -3652,7 +3682,7 @@
         }
     }
 
-    private void onTouchMove(MotionEvent ev) {
+    private void onTouchMove(MotionEvent ev, MotionEvent vtev) {
         int pointerIndex = ev.findPointerIndex(mActivePointerId);
         if (pointerIndex == -1) {
             pointerIndex = 0;
@@ -3673,7 +3703,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
@@ -3693,7 +3723,7 @@
                 break;
             case TOUCH_MODE_SCROLL:
             case TOUCH_MODE_OVERSCROLL:
-                scrollIfNeeded(y);
+                scrollIfNeeded(y, vtev);
                 break;
         }
     }
@@ -3935,6 +3965,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) {
@@ -4070,6 +4143,7 @@
             mLastY = Integer.MIN_VALUE;
             initOrResetVelocityTracker();
             mVelocityTracker.addMovement(ev);
+            startNestedScroll(SCROLL_AXIS_VERTICAL);
             if (touchMode == TOUCH_MODE_FLING) {
                 return true;
             }
@@ -4087,7 +4161,7 @@
                 final int y = (int) ev.getY(pointerIndex);
                 initVelocityTrackerIfNotExists();
                 mVelocityTracker.addMovement(ev);
-                if (startScrollIfNeeded(y)) {
+                if (startScrollIfNeeded(y, null)) {
                     return true;
                 }
                 break;
@@ -4101,6 +4175,7 @@
             mActivePointerId = INVALID_POINTER;
             recycleVelocityTracker();
             reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+            stopNestedScroll();
             break;
         }
 
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index e4575e5..51759c5 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -649,7 +649,8 @@
     private class OverflowPopup extends MenuPopupHelper {
         public OverflowPopup(Context context, MenuBuilder menu, View anchorView,
                 boolean overflowOnly) {
-            super(context, menu, anchorView, overflowOnly);
+            super(context, menu, anchorView, overflowOnly,
+                    com.android.internal.R.attr.actionOverflowMenuStyle);
             setGravity(Gravity.END);
             setCallback(mPopupPresenterCallback);
         }
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 10ec105..f91865b 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -622,8 +622,8 @@
             // only set this if the dropdown is not always visible
             mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
             mPopup.setTouchInterceptor(mTouchInterceptor);
-            mPopup.showAsDropDown(getAnchorView(),
-                    mDropDownHorizontalOffset, mDropDownVerticalOffset, mDropDownGravity);
+            mPopup.showAsDropDown(getAnchorView(), mDropDownHorizontalOffset,
+                    mDropDownVerticalOffset, mDropDownGravity);
             mDropDownList.setSelection(ListView.INVALID_POSITION);
             
             if (!mModal || mDropDownList.isInTouchMode()) {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 6e71a5c..01632ae 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.R;
 
+import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -116,6 +117,10 @@
     private Drawable mAboveAnchorBackgroundDrawable;
     private Drawable mBelowAnchorBackgroundDrawable;
 
+    // Temporary animation centers. Should be moved into window params?
+    private int mAnchorRelativeX;
+    private int mAnchorRelativeY;
+
     private boolean mAboveAnchor;
     private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
     
@@ -129,12 +134,14 @@
     };
 
     private WeakReference<View> mAnchor;
-    private OnScrollChangedListener mOnScrollChangedListener =
+
+    private final OnScrollChangedListener mOnScrollChangedListener =
         new OnScrollChangedListener() {
+            @Override
             public void onScrollChanged() {
-                View anchor = mAnchor != null ? mAnchor.get() : null;
+                final View anchor = mAnchor != null ? mAnchor.get() : null;
                 if (anchor != null && mPopupView != null) {
-                    WindowManager.LayoutParams p = (WindowManager.LayoutParams)
+                    final WindowManager.LayoutParams p = (WindowManager.LayoutParams)
                             mPopupView.getLayoutParams();
 
                     updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
@@ -143,7 +150,9 @@
                 }
             }
         };
+
     private int mAnchorXoff, mAnchorYoff, mAnchoredGravity;
+    private boolean mOverlapAnchor;
 
     private boolean mPopupViewInitialLayoutDirectionInherited;
 
@@ -187,6 +196,7 @@
                 attrs, com.android.internal.R.styleable.PopupWindow, defStyleAttr, defStyleRes);
 
         mBackground = a.getDrawable(R.styleable.PopupWindow_popupBackground);
+        mOverlapAnchor = a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false);
 
         final int animStyle = a.getResourceId(R.styleable.PopupWindow_popupAnimationStyle, -1);
         mAnimationStyle = animStyle == com.android.internal.R.style.Animation_PopupWindow ? -1 :
@@ -934,9 +944,9 @@
                 // do the job.
                 if (mAboveAnchorBackgroundDrawable != null) {
                     if (mAboveAnchor) {
-                        mPopupView.setBackgroundDrawable(mAboveAnchorBackgroundDrawable);
+                        mPopupView.setBackground(mAboveAnchorBackgroundDrawable);
                     } else {
-                        mPopupView.setBackgroundDrawable(mBelowAnchorBackgroundDrawable);
+                        mPopupView.setBackground(mBelowAnchorBackgroundDrawable);
                     }
                 } else {
                     mPopupView.refreshDrawableState();
@@ -1114,36 +1124,43 @@
         }
         return mAnimationStyle;
     }
-    
+
     /**
-     * <p>Positions the popup window on screen. When the popup window is too
-     * tall to fit under the anchor, a parent scroll view is seeked and scrolled
-     * up to reclaim space. If scrolling is not possible or not enough, the
-     * popup window gets moved on top of the anchor.</p>
-     *
-     * <p>The height must have been set on the layout parameters prior to
-     * calling this method.</p>
-     *
+     * Positions the popup window on screen. When the popup window is too tall
+     * to fit under the anchor, a parent scroll view is seeked and scrolled up
+     * to reclaim space. If scrolling is not possible or not enough, the popup
+     * window gets moved on top of the anchor.
+     * <p>
+     * The height must have been set on the layout parameters prior to calling
+     * this method.
+     * 
      * @param anchor the view on which the popup window must be anchored
      * @param p the layout parameters used to display the drop down
-     *
+     * @param xoff horizontal offset used to adjust for background padding
+     * @param yoff vertical offset used to adjust for background padding
+     * @param gravity horizontal gravity specifying popup alignment
      * @return true if the popup is translated upwards to fit on screen
      */
-    private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
-            int xoff, int yoff, int gravity) {
-
+    private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff,
+            int yoff, int gravity) {
         final int anchorHeight = anchor.getHeight();
+        final int anchorWidth = anchor.getWidth();
+        if (mOverlapAnchor) {
+            yoff -= anchorHeight;
+        }
+
         anchor.getLocationInWindow(mDrawingLocation);
         p.x = mDrawingLocation[0] + xoff;
         p.y = mDrawingLocation[1] + anchorHeight + yoff;
 
-        final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection()) &
-                Gravity.HORIZONTAL_GRAVITY_MASK;
+        final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection())
+                & Gravity.HORIZONTAL_GRAVITY_MASK;
         if (hgrav == Gravity.RIGHT) {
-            // Flip the location to align the right sides of the popup and anchor instead of left
-            p.x -= mPopupWidth - anchor.getWidth();
+            // Flip the location to align the right sides of the popup and
+            // anchor instead of left.
+            p.x -= mPopupWidth - anchorWidth;
         }
-        
+
         boolean onTop = false;
 
         p.gravity = Gravity.LEFT | Gravity.TOP;
@@ -1152,60 +1169,58 @@
         final Rect displayFrame = new Rect();
         anchor.getWindowVisibleDisplayFrame(displayFrame);
 
-        int screenY = mScreenLocation[1] + anchorHeight + yoff;
-        
+        final int screenY = mScreenLocation[1] + anchorHeight + yoff;
         final View root = anchor.getRootView();
-        if (screenY + mPopupHeight > displayFrame.bottom ||
-                p.x + mPopupWidth - root.getWidth() > 0) {
-            // if the drop down disappears at the bottom of the screen. we try to
-            // scroll a parent scrollview or move the drop down back up on top of
-            // the edit box
+        if (screenY + mPopupHeight > displayFrame.bottom
+                || p.x + mPopupWidth - root.getWidth() > 0) {
+            // If the drop down disappears at the bottom of the screen, we try
+            // to scroll a parent scrollview or move the drop down back up on
+            // top of the edit box.
             if (mAllowScrollingAnchorParent) {
-                int scrollX = anchor.getScrollX();
-                int scrollY = anchor.getScrollY();
-                Rect r = new Rect(scrollX, scrollY,  scrollX + mPopupWidth + xoff,
-                        scrollY + mPopupHeight + anchor.getHeight() + yoff);
+                final int scrollX = anchor.getScrollX();
+                final int scrollY = anchor.getScrollY();
+                final Rect r = new Rect(scrollX, scrollY, scrollX + mPopupWidth + xoff,
+                        scrollY + mPopupHeight + anchorHeight + yoff);
                 anchor.requestRectangleOnScreen(r, true);
             }
 
-            // now we re-evaluate the space available, and decide from that
+            // Now we re-evaluate the space available, and decide from that
             // whether the pop-up will go above or below the anchor.
             anchor.getLocationInWindow(mDrawingLocation);
             p.x = mDrawingLocation[0] + xoff;
-            p.y = mDrawingLocation[1] + anchor.getHeight() + yoff;
+            p.y = mDrawingLocation[1] + anchorHeight + yoff;
 
-            // Preserve the gravity adjustment
+            // Preserve the gravity adjustment.
             if (hgrav == Gravity.RIGHT) {
-                p.x -= mPopupWidth - anchor.getWidth();
+                p.x -= mPopupWidth - anchorWidth;
             }
-            
-            // determine whether there is more space above or below the anchor
+
+            // Determine whether there is more space above or below the anchor.
             anchor.getLocationOnScreen(mScreenLocation);
-            
-            onTop = (displayFrame.bottom - mScreenLocation[1] - anchor.getHeight() - yoff) <
+            onTop = (displayFrame.bottom - mScreenLocation[1] - anchorHeight - yoff) <
                     (mScreenLocation[1] - yoff - displayFrame.top);
             if (onTop) {
                 p.gravity = Gravity.LEFT | Gravity.BOTTOM;
                 p.y = root.getHeight() - mDrawingLocation[1] + yoff;
             } else {
-                p.y = mDrawingLocation[1] + anchor.getHeight() + yoff;
+                p.y = mDrawingLocation[1] + anchorHeight + yoff;
             }
         }
 
         if (mClipToScreen) {
             final int displayFrameWidth = displayFrame.right - displayFrame.left;
-
-            int right = p.x + p.width;
+            final int right = p.x + p.width;
             if (right > displayFrameWidth) {
                 p.x -= right - displayFrameWidth;
             }
+
             if (p.x < displayFrame.left) {
                 p.x = displayFrame.left;
                 p.width = Math.min(p.width, displayFrameWidth);
             }
 
             if (onTop) {
-                int popupTop = mScreenLocation[1] + yoff - mPopupHeight;
+                final int popupTop = mScreenLocation[1] + yoff - mPopupHeight;
                 if (popupTop < 0) {
                     p.y += popupTop;
                 }
@@ -1215,7 +1230,11 @@
         }
 
         p.gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
-        
+
+        // Compute the position of the anchor relative to the popup.
+        mAnchorRelativeX = mDrawingLocation[0] - p.x + anchorHeight / 2;
+        mAnchorRelativeY = mDrawingLocation[1] - p.y + anchorWidth / 2;
+
         return onTop;
     }
     
@@ -1503,7 +1522,8 @@
         }
 
         WeakReference<View> oldAnchor = mAnchor;
-        final boolean needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);
+        final boolean needsUpdate = updateLocation
+                && (mAnchorXoff != xoff || mAnchorYoff != yoff);
         if (oldAnchor == null || oldAnchor.get() != anchor || (needsUpdate && !mIsDropdown)) {
             registerForScrollChanged(anchor, xoff, yoff, gravity);
         } else if (needsUpdate) {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 3e46f68..0fa75a6 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();
 
@@ -627,7 +628,8 @@
                 final int y = (int) ev.getY(activePointerIndex);
                 int deltaY = mLastMotionY - y;
                 if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
-                    deltaY -= mScrollConsumed[1] + mScrollOffset[1];
+                    deltaY -= mScrollConsumed[1];
+                    vtev.offsetLocation(0, mScrollOffset[1]);
                 }
                 if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
                     final ViewParent parent = getParent();
@@ -643,7 +645,7 @@
                 }
                 if (mIsBeingDragged) {
                     // Scroll to follow the motion event
-                    mLastMotionY = y;
+                    mLastMotionY = y - mScrollOffset[1];
 
                     final int oldY = mScrollY;
                     final int range = getScrollRange();
@@ -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;
     }
 
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 1bb577b..04547495 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -59,11 +59,10 @@
     void noteVibratorOff(int uid);
     void noteStartGps(int uid);
     void noteStopGps(int uid);
-    void noteScreenOn();
+    void noteScreenState(int state);
     void noteScreenBrightness(int brightness);
-    void noteScreenOff();
-    void noteInputEvent();
     void noteUserActivity(int uid, int event);
+    void noteInteractive(boolean interactive);
     void noteMobileRadioPowerState(int powerState, long timestampNs);
     void notePhoneOn();
     void notePhoneOff();
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/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index cba09d1..e3f21cf 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -227,25 +227,39 @@
         if (imList.size() <= 1) {
             return null;
         }
+        // Here we have two rotation groups, depending on the returned boolean value of
+        // {@link InputMethodInfo#supportsSwitchingToNextInputMethod()}.
+        final boolean expectedValueOfSupportsSwitchingToNextInputMethod =
+                imi.supportsSwitchingToNextInputMethod();
         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;
+            // Skip until the current IME/subtype is found.
+            if (!isli.mImi.equals(imi) || isli.mSubtypeId != currentSubtypeId) {
+                continue;
             }
+            // Found the current IME/subtype. Start searching the next IME/subtype from here.
+            for (int j = 0; j < N - 1; ++j) {
+                final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
+                // Skip if the candidate doesn't belong to the expected rotation group.
+                if (expectedValueOfSupportsSwitchingToNextInputMethod !=
+                        candidate.mImi.supportsSwitchingToNextInputMethod()) {
+                    continue;
+                }
+                // Skip if searching inside the current IME only, but the candidate is not
+                // the current IME.
+                if (onlyCurrentIme && !candidate.mImi.equals(imi)) {
+                    continue;
+                }
+                return candidate;
+            }
+            // No appropriate IME/subtype is found in the list. Give up.
+            return null;
         }
+        // The current IME/subtype is not found in the list. Give up.
         return null;
     }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f63fa8a..1aff190 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -51,6 +51,7 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.util.TimeUtils;
+import android.view.Display;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.net.NetworkStatsFactory;
@@ -88,7 +89,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 104 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 105 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -237,13 +238,14 @@
     int mWakeLockNesting;
     boolean mWakeLockImportant;
 
-    boolean mScreenOn;
+    int mScreenState = Display.STATE_UNKNOWN;
     StopwatchTimer mScreenOnTimer;
 
     int mScreenBrightnessBin = -1;
     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
 
-    Counter mInputEventCounter;
+    boolean mInteractive;
+    StopwatchTimer mInteractiveTimer;
 
     boolean mPhoneOn;
     StopwatchTimer mPhoneOnTimer;
@@ -2661,58 +2663,61 @@
         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
     }
 
-    public void noteScreenOnLocked() {
-        if (!mScreenOn) {
-            final long elapsedRealtime = SystemClock.elapsedRealtime();
-            final long uptime = SystemClock.uptimeMillis();
-            mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
-                    + Integer.toHexString(mHistoryCur.states));
-            addHistoryRecordLocked(elapsedRealtime, uptime);
-            mScreenOn = true;
-            mScreenOnTimer.startRunningLocked(elapsedRealtime);
-            if (mScreenBrightnessBin >= 0) {
-                mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
-            }
+    public void noteScreenStateLocked(int state) {
+        if (mScreenState != state) {
+            final int oldState = mScreenState;
+            mScreenState = state;
+            if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
+                    + ", newState=" + Display.stateToString(state));
 
-            updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
-                    SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
+            if (state == Display.STATE_ON) {
+                // Screen turning on.
+                final long elapsedRealtime = SystemClock.elapsedRealtime();
+                final long uptime = SystemClock.uptimeMillis();
+                mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
+                if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
+                        + Integer.toHexString(mHistoryCur.states));
+                addHistoryRecordLocked(elapsedRealtime, uptime);
+                mScreenOnTimer.startRunningLocked(elapsedRealtime);
+                if (mScreenBrightnessBin >= 0) {
+                    mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
+                }
 
-            // Fake a wake lock, so we consider the device waked as long
-            // as the screen is on.
-            noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
-                    elapsedRealtime, uptime);
+                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
+                        SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
 
-            // Update discharge amounts.
-            if (mOnBatteryInternal) {
-                updateDischargeScreenLevelsLocked(false, true);
-            }
-        }
-    }
+                // Fake a wake lock, so we consider the device waked as long
+                // as the screen is on.
+                noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
+                        elapsedRealtime, uptime);
 
-    public void noteScreenOffLocked() {
-        if (mScreenOn) {
-            final long elapsedRealtime = SystemClock.elapsedRealtime();
-            final long uptime = SystemClock.uptimeMillis();
-            mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
-                    + Integer.toHexString(mHistoryCur.states));
-            addHistoryRecordLocked(elapsedRealtime, uptime);
-            mScreenOn = false;
-            mScreenOnTimer.stopRunningLocked(elapsedRealtime);
-            if (mScreenBrightnessBin >= 0) {
-                mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
-            }
+                // Update discharge amounts.
+                if (mOnBatteryInternal) {
+                    updateDischargeScreenLevelsLocked(false, true);
+                }
+            } else if (oldState == Display.STATE_ON) {
+                // Screen turning off or dozing.
+                final long elapsedRealtime = SystemClock.elapsedRealtime();
+                final long uptime = SystemClock.uptimeMillis();
+                mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
+                if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
+                        + Integer.toHexString(mHistoryCur.states));
+                addHistoryRecordLocked(elapsedRealtime, uptime);
+                mScreenOnTimer.stopRunningLocked(elapsedRealtime);
+                if (mScreenBrightnessBin >= 0) {
+                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
+                }
 
-            noteStopWakeLocked(-1, -1, "screen", WAKE_TYPE_PARTIAL,
-                    elapsedRealtime, uptime);
+                noteStopWakeLocked(-1, -1, "screen", WAKE_TYPE_PARTIAL,
+                        elapsedRealtime, uptime);
 
-            updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
-                    SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
+                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
+                        SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
 
-            // Update discharge amounts.
-            if (mOnBatteryInternal) {
-                updateDischargeScreenLevelsLocked(true, false);
+                // Update discharge amounts.
+                if (mOnBatteryInternal) {
+                    updateDischargeScreenLevelsLocked(true, false);
+                }
             }
         }
     }
@@ -2730,7 +2735,7 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime, uptime);
-            if (mScreenOn) {
+            if (mScreenState == Display.STATE_ON) {
                 if (mScreenBrightnessBin >= 0) {
                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
                 }
@@ -2740,10 +2745,6 @@
         }
     }
 
-    public void noteInputEventAtomic() {
-        mInputEventCounter.stepAtomic();
-    }
-
     public void noteUserActivityLocked(int uid, int event) {
         if (mOnBatteryInternal) {
             uid = mapUid(uid);
@@ -2751,6 +2752,19 @@
         }
     }
 
+    public void noteInteractiveLocked(boolean interactive) {
+        if (mInteractive != interactive) {
+            final long elapsedRealtime = SystemClock.elapsedRealtime();
+            mInteractive = interactive;
+            if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
+            if (interactive) {
+                mInteractiveTimer.startRunningLocked(elapsedRealtime);
+            } else {
+                mInteractiveTimer.stopRunningLocked(elapsedRealtime);
+            }
+        }
+    }
+
     public void noteMobileRadioPowerState(int powerState, long timestampNs) {
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         final long uptime = SystemClock.uptimeMillis();
@@ -3449,8 +3463,8 @@
                 elapsedRealtimeUs, which);
     }
 
-    @Override public int getInputEventCount(int which) {
-        return mInputEventCounter.getCountLocked(which);
+    @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
+        return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
 
     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
@@ -5499,7 +5513,6 @@
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase);
         }
-        mInputEventCounter = new Counter(mOnBatteryTimeBase);
         mPhoneOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null,
@@ -5530,6 +5543,7 @@
         }
         mAudioOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase);
         mVideoOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
+        mInteractiveTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
         mOnBattery = mOnBatteryInternal = false;
         long uptime = SystemClock.uptimeMillis() * 1000;
         long realtime = SystemClock.elapsedRealtime() * 1000;
@@ -5713,7 +5727,7 @@
     }
 
     public boolean isScreenOn() {
-        return mScreenOn;
+        return mScreenState == Display.STATE_ON;
     }
 
     void initTimes(long uptime, long realtime) {
@@ -5753,7 +5767,7 @@
         mOnBatteryTimeBase.reset(uptime, realtime);
         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
-            if (mScreenOn) {
+            if (mScreenState == Display.STATE_ON) {
                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
                 mDischargeScreenOffUnplugLevel = 0;
             } else {
@@ -5773,7 +5787,7 @@
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             mScreenBrightnessTimer[i].reset(false);
         }
-        mInputEventCounter.reset(false);
+        mInteractiveTimer.reset(false);
         mPhoneOnTimer.reset(false);
         mAudioOnTimer.reset(false);
         mVideoOnTimer.reset(false);
@@ -5874,7 +5888,8 @@
         updateKernelWakelocksLocked();
         updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
         if (mOnBatteryInternal) {
-            updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn);
+            final boolean screenOn = mScreenState == Display.STATE_ON;
+            updateDischargeScreenLevelsLocked(screenOn, screenOn);
         }
     }
 
@@ -5888,6 +5903,7 @@
 
         final long uptime = mSecUptime * 1000;
         final long realtime = mSecRealtime * 1000;
+        final boolean screenOn = mScreenState == Display.STATE_ON;
         if (onBattery) {
             // We will reset our status if we are unplugging after the
             // battery was last full, or the level is at 100, or
@@ -5916,7 +5932,7 @@
             }
             addHistoryRecordLocked(mSecRealtime, mSecUptime);
             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
-            if (mScreenOn) {
+            if (screenOn) {
                 mDischargeScreenOnUnplugLevel = level;
                 mDischargeScreenOffUnplugLevel = 0;
             } else {
@@ -5925,7 +5941,7 @@
             }
             mDischargeAmountScreenOn = 0;
             mDischargeAmountScreenOff = 0;
-            updateTimeBasesLocked(true, !mScreenOn, uptime, realtime);
+            updateTimeBasesLocked(true, !screenOn, uptime, realtime);
         } else {
             pullPendingStateUpdatesLocked();
             mHistoryCur.batteryLevel = (byte)level;
@@ -5938,8 +5954,8 @@
                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
             }
-            updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn);
-            updateTimeBasesLocked(false, !mScreenOn, uptime, realtime);
+            updateDischargeScreenLevelsLocked(screenOn, screenOn);
+            updateTimeBasesLocked(false, !screenOn, uptime, realtime);
             mNumChargeStepDurations = 0;
             mLastChargeStepLevel = level;
             mLastChargeStepTime = -1;
@@ -6475,7 +6491,7 @@
     public int getDischargeAmountScreenOn() {
         synchronized(this) {
             int val = mDischargeAmountScreenOn;
-            if (mOnBattery && mScreenOn
+            if (mOnBattery && mScreenState == Display.STATE_ON
                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
             }
@@ -6486,7 +6502,7 @@
     public int getDischargeAmountScreenOnSinceCharge() {
         synchronized(this) {
             int val = mDischargeAmountScreenOnSinceCharge;
-            if (mOnBattery && mScreenOn
+            if (mOnBattery && mScreenState == Display.STATE_ON
                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
             }
@@ -6497,7 +6513,7 @@
     public int getDischargeAmountScreenOff() {
         synchronized(this) {
             int val = mDischargeAmountScreenOff;
-            if (mOnBattery && !mScreenOn
+            if (mOnBattery && mScreenState != Display.STATE_ON
                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
             }
@@ -6508,7 +6524,7 @@
     public int getDischargeAmountScreenOffSinceCharge() {
         synchronized(this) {
             int val = mDischargeAmountScreenOffSinceCharge;
-            if (mOnBattery && !mScreenOn
+            if (mOnBattery && mScreenState != Display.STATE_ON
                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
             }
@@ -6915,12 +6931,13 @@
 
         mStartCount++;
 
-        mScreenOn = false;
+        mScreenState = Display.STATE_UNKNOWN;
         mScreenOnTimer.readSummaryFromParcelLocked(in);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
         }
-        mInputEventCounter.readSummaryFromParcelLocked(in);
+        mInteractive = false;
+        mInteractiveTimer.readSummaryFromParcelLocked(in);
         mPhoneOn = false;
         mPhoneOnTimer.readSummaryFromParcelLocked(in);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -7175,7 +7192,7 @@
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
-        mInputEventCounter.writeSummaryFromParcelLocked(out);
+        mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -7431,13 +7448,12 @@
         mOnBatteryTimeBase.readFromParcel(in);
         mOnBatteryScreenOffTimeBase.readFromParcel(in);
 
-        mScreenOn = false;
+        mScreenState = Display.STATE_UNKNOWN;
         mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase, in);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase,
                     in);
         }
-        mInputEventCounter = new Counter(mOnBatteryTimeBase, in);
         mPhoneOn = false;
         mPhoneOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -7461,19 +7477,25 @@
         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
         mWifiOn = false;
-        mWifiOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+        mWifiOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
         mGlobalWifiRunning = false;
-        mGlobalWifiRunningTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+        mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase, in);
         for (int i=0; i<NUM_WIFI_STATES; i++) {
             mWifiStateTimer[i] = new StopwatchTimer(null, -600-i,
                     null, mOnBatteryTimeBase, in);
         }
         mBluetoothOn = false;
-        mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+        mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase, in);
         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
             mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i,
                     null, mOnBatteryTimeBase, in);
         }
+        mAudioOn = false;
+        mAudioOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase);
+        mVideoOn = false;
+        mVideoOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
+        mInteractive = false;
+        mInteractiveTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase, in);
         mDischargeUnplugLevel = in.readInt();
         mDischargePlugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
@@ -7571,7 +7593,7 @@
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
         }
-        mInputEventCounter.writeToParcel(out);
+        mInteractiveTimer.writeToParcel(out, uSecRealtime);
         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
@@ -7688,8 +7710,8 @@
                 pr.println("*** Screen brightness #" + i + ":");
                 mScreenBrightnessTimer[i].logState(pr, "  ");
             }
-            pr.println("*** Input event counter:");
-            mInputEventCounter.logState(pr, "  ");
+            pr.println("*** Interactive timer:");
+            mInteractiveTimer.logState(pr, "  ");
             pr.println("*** Phone timer:");
             mPhoneOnTimer.logState(pr, "  ");
             for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 6428e15..caa6b98 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -42,7 +42,7 @@
             out int[] switches, out List<IBinder> binders);
     void onPanelRevealed();
     void onPanelHidden();
-    void onNotificationClick(String pkg, String tag, int id, int userId);
+    void onNotificationClick(String key);
     void onNotificationError(String pkg, String tag, int id,
             int uid, int initialPid, String message, int userId);
     void onClearAllNotifications(int userId);
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/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index d664058..5a12893 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -53,6 +53,7 @@
     private final MenuAdapter mAdapter;
     private final boolean mOverflowOnly;
     private final int mPopupMaxWidth;
+    private final int mPopupStyleAttr;
 
     private View mAnchorView;
     private ListPopupWindow mPopup;
@@ -72,20 +73,21 @@
     private int mDropDownGravity = Gravity.NO_GRAVITY;
 
     public MenuPopupHelper(Context context, MenuBuilder menu) {
-        this(context, menu, null, false);
+        this(context, menu, null, false, com.android.internal.R.attr.popupMenuStyle);
     }
 
     public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) {
-        this(context, menu, anchorView, false);
+        this(context, menu, anchorView, false, com.android.internal.R.attr.popupMenuStyle);
     }
 
-    public MenuPopupHelper(Context context, MenuBuilder menu,
-            View anchorView, boolean overflowOnly) {
+    public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView,
+            boolean overflowOnly, int popupStyleAttr) {
         mContext = context;
         mInflater = LayoutInflater.from(context);
         mMenu = menu;
         mAdapter = new MenuAdapter(mMenu);
         mOverflowOnly = overflowOnly;
+        mPopupStyleAttr = popupStyleAttr;
 
         final Resources res = context.getResources();
         mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2,
@@ -119,7 +121,7 @@
     }
 
     public boolean tryShow() {
-        mPopup = new ListPopupWindow(mContext, null, com.android.internal.R.attr.popupMenuStyle);
+        mPopup = new ListPopupWindow(mContext, null, mPopupStyleAttr);
         mPopup.setOnDismissListener(this);
         mPopup.setOnItemClickListener(this);
         mPopup.setAdapter(mAdapter);
@@ -272,7 +274,7 @@
     @Override
     public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
         if (subMenu.hasVisibleItems()) {
-            MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView, false);
+            MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView);
             subPopup.setCallback(mPresenterCallback);
 
             boolean preserveIconSpacing = false;
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index 01bee0c..19d58bf 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -576,7 +576,7 @@
     }
 
     public int getActionBarHideOffset() {
-        return -((int) mActionBarTop.getTranslationY());
+        return mActionBarTop != null ? -((int) mActionBarTop.getTranslationY()) : 0;
     }
 
     public void setActionBarHideOffset(int offset) {
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..8bd2e4f 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 \
@@ -140,6 +141,7 @@
 	android_util_FileObserver.cpp \
 	android/opengl/poly_clip.cpp.arm \
 	android/opengl/util.cpp.arm \
+	android_server_FingerprintManager.cpp \
 	android_server_NetworkManagementSocketTagger.cpp \
 	android_server_Watchdog.cpp \
 	android_ddm_DdmHandleNativeHeap.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/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index b78b131..621534e 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -221,7 +221,7 @@
     }
 
     fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
-            "(Ljava/lang/Object;)V");
+            "(Ljava/lang/ref/WeakReference;)V");
     if (fields.postEvent == NULL) {
         ALOGE("can't find android/graphics/SurfaceTexture.postEventFromNative");
     }
@@ -338,7 +338,7 @@
 
 static JNINativeMethod gSurfaceTextureMethods[] = {
     {"nativeClassInit",            "()V",   (void*)SurfaceTexture_classInit },
-    {"nativeInit",                 "(IZLjava/lang/Object;)V", (void*)SurfaceTexture_init },
+    {"nativeInit",                 "(IZLjava/lang/ref/WeakReference;)V", (void*)SurfaceTexture_init },
     {"nativeFinalize",             "()V",   (void*)SurfaceTexture_finalize },
     {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
     {"nativeUpdateTexImage",       "()V",   (void*)SurfaceTexture_updateTexImage },
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_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index f4bab26..fedb1b2 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -22,6 +22,7 @@
 // keep these values in sync with AudioFormat.java
 #define ENCODING_PCM_16BIT 2
 #define ENCODING_PCM_8BIT  3
+#define ENCODING_PCM_FLOAT 4
 
 static inline audio_format_t audioFormatToNative(int audioFormat)
 {
@@ -30,6 +31,8 @@
         return AUDIO_FORMAT_PCM_16_BIT;
     case ENCODING_PCM_8BIT:
         return AUDIO_FORMAT_PCM_8_BIT;
+    case ENCODING_PCM_FLOAT:
+        return AUDIO_FORMAT_PCM_FLOAT;
     default:
         return AUDIO_FORMAT_INVALID;
     }
diff --git a/core/jni/android_server_FingerprintManager.cpp b/core/jni/android_server_FingerprintManager.cpp
new file mode 100644
index 0000000..f8a1fd9
--- /dev/null
+++ b/core/jni/android_server_FingerprintManager.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Fingerprint-JNI"
+
+#include "JNIHelp.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <utils/Log.h>
+
+namespace android {
+
+static struct {
+    jclass clazz;
+    jmethodID notify;
+} gFingerprintManagerClassInfo;
+
+static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout) {
+    return -1; // TODO
+}
+
+static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerprintId) {
+    return -1; // TODO
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod g_methods[] = {
+    { "nativeEnroll", "(I)I", (void*)nativeEnroll },
+    { "nativeRemove", "(I)I", (void*)nativeRemove },
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
+        var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find static method" methodName);
+
+#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
+        var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find method" methodName);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_FingerprintManager(JNIEnv* env) {
+    FIND_CLASS(gFingerprintManagerClassInfo.clazz,
+            "android/service/fingerprint/FingerprintManager");
+    GET_METHOD_ID(gFingerprintManagerClassInfo.notify, gFingerprintManagerClassInfo.clazz,
+            "notify", "(III)V");
+    return AndroidRuntime::registerNativeMethods(
+        env, "com/android/service/fingerprint/FingerprintManager", g_methods, NELEM(g_methods));
+}
+
+} // namespace android
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index ef5ebd0..3aa179d 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -49,6 +49,7 @@
 #include <Stencil.h>
 #include <Rect.h>
 #include <RenderNode.h>
+#include <CanvasProperty.h>
 
 #include <TextLayout.h>
 #include <TextLayoutCache.h>
@@ -544,6 +545,16 @@
     renderer->drawCircle(x, y, radius, paint);
 }
 
+static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
+        jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
+    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
+    CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
+    CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
+    CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
+    renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
+}
+
 static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jlong paintPtr) {
@@ -1041,6 +1052,7 @@
     { "nDrawRects",         "(J[FIJ)V",        (void*) android_view_GLES20Canvas_drawRects },
     { "nDrawRoundRect",     "(JFFFFFFJ)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
     { "nDrawCircle",        "(JFFFJ)V",        (void*) android_view_GLES20Canvas_drawCircle },
+    { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_GLES20Canvas_drawCircleProps },
     { "nDrawOval",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawOval },
     { "nDrawArc",           "(JFFFFFFZJ)V",    (void*) android_view_GLES20Canvas_drawArc },
     { "nDrawPoints",        "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawPoints },
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index b92c992..3be013b 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -16,8 +16,6 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
-#include "android_view_RenderNodeAnimator.h"
-
 #include "jni.h"
 #include "GraphicsJNI.h"
 #include <nativehelper/JNIHelp.h>
@@ -47,46 +45,93 @@
     return env;
 }
 
-RenderNodeAnimator::RenderNodeAnimator(JNIEnv* env, jobject weakThis,
-                RenderProperty property, DeltaValueType deltaType, float delta)
-        : RenderPropertyAnimator(property, deltaType, delta) {
-    mWeakThis = env->NewGlobalRef(weakThis);
-    env->GetJavaVM(&mJvm);
-}
+class AnimationListenerBridge : public AnimationListener {
+public:
+    // This holds a strong reference to a Java WeakReference<T> object. This avoids
+    // cyclic-references-of-doom. If you think "I know, just use NewWeakGlobalRef!"
+    // then you end up with basically a PhantomReference, which is totally not
+    // what we want.
+    AnimationListenerBridge(JNIEnv* env, jobject weakThis) {
+        mWeakThis = env->NewGlobalRef(weakThis);
+        env->GetJavaVM(&mJvm);
+    }
 
-RenderNodeAnimator::~RenderNodeAnimator() {
-    JNIEnv* env = getEnv(mJvm);
-    env->DeleteGlobalRef(mWeakThis);
-    mWeakThis = NULL;
-}
+    virtual ~AnimationListenerBridge() {
+        JNIEnv* env = getEnv(mJvm);
+        env->DeleteGlobalRef(mWeakThis);
+        mWeakThis = NULL;
+    }
 
-void RenderNodeAnimator::callOnFinished() {
-    JNIEnv* env = getEnv(mJvm);
-    env->CallStaticVoidMethod(
-            gRenderNodeAnimatorClassInfo.clazz,
-            gRenderNodeAnimatorClassInfo.callOnFinished,
-            mWeakThis);
-}
+    virtual void onAnimationFinished(BaseAnimator*) {
+        JNIEnv* env = getEnv(mJvm);
+        env->CallStaticVoidMethod(
+                gRenderNodeAnimatorClassInfo.clazz,
+                gRenderNodeAnimatorClassInfo.callOnFinished,
+                mWeakThis);
+    }
 
-static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
-        jint property, jint deltaType, jfloat deltaValue) {
-    LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderNodeAnimator::ALPHA,
+private:
+    JavaVM* mJvm;
+    jobject mWeakThis;
+};
+
+static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint property) {
+    LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderPropertyAnimator::ALPHA,
             "Invalid property %d", property);
+    return static_cast<RenderPropertyAnimator::RenderProperty>(property);
+}
+
+static inline RenderPropertyAnimator::DeltaValueType toDeltaType(jint deltaType) {
     LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA
             && deltaType != RenderPropertyAnimator::ABSOLUTE,
             "Invalid delta type %d", deltaType);
+    return static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType);
+}
 
-    RenderNodeAnimator* animator = new RenderNodeAnimator(env, weakThis,
-            static_cast<RenderPropertyAnimator::RenderProperty>(property),
-            static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType),
-            deltaValue);
+static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) {
+    LOG_ALWAYS_FATAL_IF(field < 0
+            || field > CanvasPropertyPaintAnimator::ALPHA,
+            "Invalid paint field %d", field);
+    return static_cast<CanvasPropertyPaintAnimator::PaintField>(field);
+}
+
+static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
+        jint propertyRaw, jint deltaTypeRaw, jfloat deltaValue) {
+    RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw);
+    RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+
+    BaseAnimator* animator = new RenderPropertyAnimator(property, deltaType, deltaValue);
     animator->incStrong(0);
+    animator->setListener(new AnimationListenerBridge(env, weakThis));
+    return reinterpret_cast<jlong>( animator );
+}
+
+static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz,
+        jobject weakThis, jlong canvasPropertyPtr, jint deltaTypeRaw, jfloat deltaValue) {
+    RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+    CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr);
+    BaseAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, deltaType, deltaValue);
+    animator->incStrong(0);
+    animator->setListener(new AnimationListenerBridge(env, weakThis));
+    return reinterpret_cast<jlong>( animator );
+}
+
+static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz,
+        jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw,
+        jint deltaTypeRaw, jfloat deltaValue) {
+    RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+    CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr);
+    CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw);
+    BaseAnimator* animator = new CanvasPropertyPaintAnimator(
+            canvasProperty, paintField, deltaType, deltaValue);
+    animator->incStrong(0);
+    animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
 
 static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) {
     LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
-    RenderNodeAnimator* animator = reinterpret_cast<RenderNodeAnimator*>(animatorPtr);
+    BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
     animator->setDuration(duration);
 }
 
@@ -106,6 +151,8 @@
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
     { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator },
+    { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyFloatAnimator },
+    { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIIF)J", (void*) createCanvasPropertyPaintAnimator },
     { "nSetDuration", "(JI)V", (void*) setDuration },
     { "nUnref", "(J)V", (void*) unref },
 #endif
diff --git a/core/jni/android_view_RenderNodeAnimator.h b/core/jni/android_view_RenderNodeAnimator.h
deleted file mode 100644
index 760ca91..0000000
--- a/core/jni/android_view_RenderNodeAnimator.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "jni.h"
-
-#ifdef USE_OPENGL_RENDERER
-
-#include <Animator.h>
-
-namespace android {
-
-class RenderNodeAnimator : public uirenderer::RenderPropertyAnimator {
-public:
-    RenderNodeAnimator(JNIEnv* env, jobject callbackObject,
-            RenderProperty property, DeltaValueType deltaType, float delta);
-    virtual ~RenderNodeAnimator();
-
-    void callOnFinished();
-
-private:
-    JavaVM* mJvm;
-    jobject mWeakThis;
-};
-
-}
-
-#endif
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c293c7a..5a935a9 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -50,6 +50,8 @@
     "android/view/Surface$OutOfResourcesException";
 
 static struct {
+    jclass clazz;
+    jmethodID ctor;
     jfieldID width;
     jfieldID height;
     jfieldID refreshRate;
@@ -346,24 +348,49 @@
     SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
 }
 
-static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz,
-        jobject tokenObj, jobject infoObj) {
+static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
+        jobject tokenObj) {
     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
-    if (token == NULL) return JNI_FALSE;
+    if (token == NULL) return NULL;
 
-    DisplayInfo info;
-    if (SurfaceComposerClient::getDisplayInfo(token, &info)) {
-        return JNI_FALSE;
+    Vector<DisplayInfo> configs;
+    if (SurfaceComposerClient::getDisplayConfigs(token, &configs) != NO_ERROR ||
+            configs.size() == 0) {
+        return NULL;
     }
 
-    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
-    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
-    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
-    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
-    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
-    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
-    env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
-    return JNI_TRUE;
+    jobjectArray configArray = env->NewObjectArray(configs.size(),
+            gPhysicalDisplayInfoClassInfo.clazz, NULL);
+
+    for (size_t c = 0; c < configs.size(); ++c) {
+        const DisplayInfo& info = configs[c];
+        jobject infoObj = env->NewObject(gPhysicalDisplayInfoClassInfo.clazz,
+                gPhysicalDisplayInfoClassInfo.ctor);
+        env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
+        env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
+        env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
+        env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
+        env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
+        env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
+        env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
+        env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj);
+        env->DeleteLocalRef(infoObj);
+    }
+
+    return configArray;
+}
+
+static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return -1;
+    return static_cast<jint>(SurfaceComposerClient::getActiveConfig(token));
+}
+
+static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj, jint id) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return JNI_FALSE;
+    status_t err = SurfaceComposerClient::setActiveConfig(token, static_cast<int>(id));
+    return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
 }
 
 static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
@@ -576,8 +603,12 @@
             (void*)nativeSetDisplayLayerStack },
     {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V",
             (void*)nativeSetDisplayProjection },
-    {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/SurfaceControl$PhysicalDisplayInfo;)Z",
-            (void*)nativeGetDisplayInfo },
+    {"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;",
+            (void*)nativeGetDisplayConfigs },
+    {"nativeGetActiveConfig", "(Landroid/os/IBinder;)I",
+            (void*)nativeGetActiveConfig },
+    {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
+            (void*)nativeSetActiveConfig },
     {"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
             (void*)nativeBlankDisplay },
     {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
@@ -598,6 +629,9 @@
             sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
 
     jclass clazz = env->FindClass("android/view/SurfaceControl$PhysicalDisplayInfo");
+    gPhysicalDisplayInfoClassInfo.clazz = static_cast<jclass>(env->NewGlobalRef(clazz));
+    gPhysicalDisplayInfoClassInfo.ctor = env->GetMethodID(gPhysicalDisplayInfoClassInfo.clazz,
+            "<init>", "()V");
     gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I");
     gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I");
     gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F");
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 58fc1e1..6ff28e3 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,
@@ -144,6 +152,18 @@
     delete proxy;
 }
 
+static void android_view_ThreadedRenderer_setFrameInterval(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jlong frameIntervalNanos) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    proxy->setFrameInterval(frameIntervalNanos);
+}
+
+static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
+        jlong proxyPtr) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    return proxy->loadSystemProperties();
+}
+
 static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -177,11 +197,11 @@
     proxy->setup(width, height);
 }
 
-static void android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jint dirtyLeft, jint dirtyTop,
+static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jlong frameTimeNanos, jint dirtyLeft, jint dirtyTop,
         jint dirtyRight, jint dirtyBottom) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->syncAndDrawFrame(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
+    return proxy->syncAndDrawFrame(frameTimeNanos, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
 }
 
 static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
@@ -253,11 +273,13 @@
     { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
     { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
+    { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval },
+    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
     { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
     { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
     { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
     { "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup },
-    { "nSyncAndDrawFrame", "(JIIII)V", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
+    { "nSyncAndDrawFrame", "(JJIIII)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
     { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
     { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3d3e86f..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
@@ -2793,7 +2793,7 @@
 
         <receiver android:name="com.android.server.BootReceiver"
                 android:primaryUserOnly="true">
-            <intent-filter>
+            <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
diff --git a/core/res/res/anim/popup_enter_quantum.xml b/core/res/res/anim/popup_enter_quantum.xml
new file mode 100644
index 0000000..79de26b
--- /dev/null
+++ b/core/res/res/anim/popup_enter_quantum.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false" >
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+           android:interpolator="@interpolator/decelerate_cubic"
+           android:duration="@android:integer/config_activityShortDur" />
+</set>
diff --git a/core/res/res/anim/popup_exit_quantum.xml b/core/res/res/anim/popup_exit_quantum.xml
new file mode 100644
index 0000000..7d7d5c5
--- /dev/null
+++ b/core/res/res/anim/popup_exit_quantum.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false" >
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+           android:interpolator="@interpolator/decelerate_cubic"
+           android:duration="@android:integer/config_activityShortDur"/>
+</set>
diff --git a/core/res/res/drawable/popup_background_quantum.xml b/core/res/res/drawable/popup_background_quantum.xml
new file mode 100644
index 0000000..7e5b003
--- /dev/null
+++ b/core/res/res/drawable/popup_background_quantum.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <corners
+        android:radius="2dp" />
+    <solid
+        android:color="?attr/colorBackground" />
+
+</shape>
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 20d306d..4358dd3 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dae"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> uur"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> minute"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> minuut"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minute"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> minuut <xliff:g id="SECONDS">%2$d</xliff:g> sekondes"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> minuut <xliff:g id="SECONDS">%2$d</xliff:g> sekond"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sekondes"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sekonde"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Titelloos&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Persoonlik"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Werk"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Dienste wat jou geld kos"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Doen dinge wat jou geld kan kos."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Jou boodskappe"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 04bfee5..7fac03f 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ቀኖች"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ቀን <xliff:g id="HOURS">%2$d</xliff:g> ሰዓ"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ቀን <xliff:g id="HOURS">%2$d</xliff:g> ሰዓ"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ሰዓ"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ሰዓ <xliff:g id="MINUTES">%2$d</xliff:g> ደቂቃ"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ሰዓ <xliff:g id="MINUTES">%2$d</xliff:g> ደቂቃ"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> ደቂቃዎች"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> ደቂቃ <xliff:g id="SECONDS">%2$d</xliff:g> ሴ"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> ደቂቃ <xliff:g id="SECONDS">%2$d</xliff:g> ሴ"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ሴ"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ሴ"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;ርዕስ አልባ&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"የግል"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"ስራ"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"ገንዘብ የሚያስወጥዎ አገልግሎቶች"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ገንዘብ የሚያስወጡህን ነገሮች አድርግ።"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"መልዕክቶችዎ"</string>
@@ -1077,7 +1068,7 @@
   </plurals>
   <plurals name="in_num_days">
     <item quantity="one" msgid="5413088743009839518">"ነገ"</item>
-    <item quantity="other" msgid="5109449375100953247">"በ<xliff:g id="COUNT">%d</xliff:g> ቀናት"</item>
+    <item quantity="other" msgid="5109449375100953247">"በ<xliff:g id="COUNT">%d</xliff:g> ቀኖች"</item>
   </plurals>
   <plurals name="abbrev_num_seconds_ago">
     <item quantity="one" msgid="1849036840200069118">"1 ሴኮንድ በፊት"</item>
@@ -1109,7 +1100,7 @@
   </plurals>
   <plurals name="abbrev_in_num_days">
     <item quantity="one" msgid="2178576254385739855">"ነገ"</item>
-    <item quantity="other" msgid="2973062968038355991">"በ<xliff:g id="COUNT">%d</xliff:g> ቀናት"</item>
+    <item quantity="other" msgid="2973062968038355991">"በ<xliff:g id="COUNT">%d</xliff:g> ቀኖች"</item>
   </plurals>
     <string name="preposition_for_date" msgid="9093949757757445117">"በ <xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="preposition_for_time" msgid="5506831244263083793">"በ <xliff:g id="TIME">%s</xliff:g>"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 83168e4..a32c74c 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> يوم"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> يوم <xliff:g id="HOURS">%2$d</xliff:g> ساعة"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> يوم <xliff:g id="HOURS">%2$d</xliff:g> ساعة"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ساعة"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ساعة <xliff:g id="MINUTES">%2$d</xliff:g> دقيقة"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ساعة <xliff:g id="MINUTES">%2$d</xliff:g> دقيقة"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> دقيقة"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> دقيقة <xliff:g id="SECONDS">%2$d</xliff:g> ثانية"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> دقيقة <xliff:g id="SECONDS">%2$d</xliff:g> ثانية"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ثانية"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ثانية"</string>
     <string name="untitled" msgid="4638956954852782576">"‏&lt;بلا عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏نظام Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"شخصي"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"عمل"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"الخدمات التي تكلفك المال"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"يمكنك تنفيذ إجراءات يمكن أن تكلفك مالاً."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"رسائلك"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 2d22cdc..3ebe798 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дни"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ден <xliff:g id="HOURS">%2$d</xliff:g> ч"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ден <xliff:g id="HOURS">%2$d</xliff:g> ч"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ч"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ч <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ч <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> мин"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Без заглавие&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Личен"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Служебен"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуги, които ви струват пари"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Извършват неща, които могат да ви струват пари."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Вашите съобщения"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index cfb77d3..a767e7f 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dies"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> hores"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minuts"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <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>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Feina"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serveis de pagament"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Dur a terme activitats de pagament."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Missatges"</string>
@@ -409,8 +400,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>
-    <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_bindVoiceInteraction" msgid="5334852580713715068">"enllaçar amb una eina d\'interacció de veu"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permet enllaçar 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>
@@ -723,8 +714,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>
-    <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_bindConditionProviderService" msgid="1180107672332704641">"enllaçar amb el servei de proveïdor de condicions"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet enllaçar amb la interfície de nivell superior d\'un servei de 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>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 868f899..1c4e8b8 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <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>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Osobní"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Práce"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Zpoplatněné služby"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Provádět činnosti, které vás mohou stát peníze."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše zprávy"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 206db12..1724de1 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dage"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> t."</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> t."</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> timer"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> t. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> t. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min."</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sek."</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sek."</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Uden titel&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personlig"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Arbejde"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjenester, der koster dig penge"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Gør ting, der kan koste dig penge."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Dine beskeder"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 87d4aa0..e527521 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> Tage"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> Tag <xliff:g id="HOURS">%2$d</xliff:g> Std."</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> Tag <xliff:g id="HOURS">%2$d</xliff:g> Std."</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> Std."</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> Std. <xliff:g id="MINUTES">%2$d</xliff:g> Min."</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> Std. <xliff:g id="MINUTES">%2$d</xliff:g> Min."</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> Min."</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> Min. <xliff:g id="SECONDS">%2$d</xliff:g> Sek."</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> Min. <xliff:g id="SECONDS">%2$d</xliff:g> Sek."</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> Sek."</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> Sek."</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Unbenannt&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Privat"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Geschäftlich"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Kostenpflichtige Dienste"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Kostenpflichtige Aktionen"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ihre Nachrichten"</string>
@@ -723,8 +714,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>
-    <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_bindConditionProviderService" msgid="1180107672332704641">"An einen Bedingungsproviderdienst binden"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ermöglicht dem Inhaber, sich an die Oberfläche eines Bedingungsproviderdienstes 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>
@@ -740,11 +731,11 @@
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Bildschirms überwachen und Telefon sperren oder alle Daten auf dem Telefon löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"Passwort zum Entsperren des Bildschirms ändern"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"Ändern Sie das Passwort zum Entsperren des Bildschirms."</string>
-    <string name="policylab_forceLock" msgid="2274085384704248431">"Display sperren"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bildschirm sperren"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"Legen Sie fest, wie und wann der Bildschirm gesperrt wird."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Alle Daten löschen"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Tablet ohne Warnung löschen"</string>
-    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Setzen Sie das Telefon auf Werkseinstellungen zurück. Dabei werden alle Daten ohne Warnung gelöscht."</string>
+    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Setzen Sie das Telefon auf die Werkseinstellungen zurück. Dabei werden alle Daten ohne Warnung gelöscht."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Den globalen Proxy des Geräts festlegen"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Den bei aktivierter Richtlinie zu verwendenden globalen Proxy des Geräts festlegen. Nur der erste Geräteadministrator kann den gültigen globalen Proxy festlegen."</string>
     <string name="policylab_expirePassword" msgid="885279151847254056">"Ablauf von Sperr-Passwort festlegen"</string>
@@ -1395,7 +1386,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>
-    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Bedingungsanbieter"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Bedingungsprovider"</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 9105cb2..296fd71 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ημέρες"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ημ. <xliff:g id="HOURS">%2$d</xliff:g> ώρες"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ημ. <xliff:g id="HOURS">%2$d</xliff:g> ώρα"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ώρες"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ώρα <xliff:g id="MINUTES">%2$d</xliff:g> λ"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ώρα <xliff:g id="MINUTES">%2$d</xliff:g> λ"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> λεπτά"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> λ. <xliff:g id="SECONDS">%2$d</xliff:g> δευτ."</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> λ <xliff:g id="SECONDS">%2$d</xliff:g> δευτ."</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> δευτ."</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> δευτ."</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Χωρίς τίτλο&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Προσωπικό"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Εργασία"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Υπηρεσίες επί πληρωμή"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Πραγματοποίηση ενεργειών για τις οποίες ενδέχεται να χρεωθείτε."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Τα μηνύματά σας"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 51a85e3..c4b7aa0 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> days"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hrs"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hr"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> hrs"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> mins"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> mins"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> secs"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> secs"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sec"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Untitled&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Work"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services that cost you money"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Do things that can cost you money."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Your messages"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 51a85e3..c4b7aa0 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> days"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hrs"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hr"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> hrs"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> mins"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> mins"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> secs"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> secs"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sec"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Untitled&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Work"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services that cost you money"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Do things that can cost you money."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Your messages"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 2a4f7e9..1225c81 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> días"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <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>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Trabajo"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios que te cuestan dinero"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Permite que las aplicaciones realicen actividades con cargo."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Tus mensajes"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 2e0d68b..1c6aa8d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> días"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <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>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt; 999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Trabajo"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios por los que tienes que pagar"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Hacer acciones por las que puede que tengas que pagar"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Tus mensajes"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 32abeb8..1c3d94a 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> päeva"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> päev <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> päev <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Pealkirjata&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥."</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Isiklik"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Töö"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tasulised teenused"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Tasuliste toimingute tegemine."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Teie sõnumid"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index c5abcbd..dbc0d43 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> روز"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> روز و <xliff:g id="HOURS">%2$d</xliff:g> ساعت"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> روز و <xliff:g id="HOURS">%2$d</xliff:g> ساعت"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ساعت"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ساعت و <xliff:g id="MINUTES">%2$d</xliff:g> دقیقه"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ساعت و <xliff:g id="MINUTES">%2$d</xliff:g> دقیقه"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> دقیقه"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> دقیقه و <xliff:g id="SECONDS">%2$d</xliff:g> ثانیه"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> دقیقه و <xliff:g id="SECONDS">%2$d</xliff:g> ثانیه"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ثانیه"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ثانیه"</string>
     <string name="untitled" msgid="4638956954852782576">"‏&lt;بدون عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"بیشتر از 999"</string>
     <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏سیستم Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"شخصی"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"محل کار"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"سرویس‌های غیر رایگان"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"انجام کارهایی که برای شما هزینه دارد."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"پیام‌های شما"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 945c7ab..03dfb12 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> päivää"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> päivä <xliff:g id="HOURS">%2$d</xliff:g> t"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> päivä <xliff:g id="HOURS">%2$d</xliff:g> t"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> t"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> t <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> t <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Nimetön&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,10 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
+    <!-- no translation found for user_owner_label (2804351898001038951) -->
+    <skip />
+    <!-- no translation found for managed_profile_label (6260850669674791528) -->
+    <skip />
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksulliset palvelut"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Suorita mahdollisesti maksullisia toimintoja."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Omat viestit"</string>
@@ -409,10 +402,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Antaa sovelluksen sitoutua VPN-palvelun ylemmän tason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sido taustakuvaan"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Antaa sovelluksen sitoutua taustakuvan ylätason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"puheohjauspalveluun sitominen"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Antaa sovelluksen luoda sidoksen puheohjauspalvelun ylätason rajapintaan. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"etänäyttöön sitoutuminen"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Antaa sovelluksen sitoutua etänäytön ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sitoudu widget-palveluun"</string>
@@ -725,10 +716,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Antaa sovelluksen noutaa, tutkia ja tyhjentää ilmoituksia (myös muiden sovelluksien lähettämiä)."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"sido ilmoituskuuntelijapalveluun"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Antaa sovelluksen sitoutua ilmoituskuuntelijan ylimmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ehtojen toimituspalveluun sitominen"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Antaa sovelluksen luoda sidoksen ehtojen toimituspalvelun ylätason rajapintaan. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Palveluntarjoajan määrityssovelluksen käynnistäminen"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Antaa luvanhaltijan käynnistää palveluntarjoajan määrityssovelluksen. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"verkon tilahavaintojen kuunteleminen"</string>
@@ -1399,8 +1388,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustakuva"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Vaihda taustakuvaa"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ilmoituskuuntelija"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ehtojen toimituspalvelu"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktivoitu"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> on aktivoinut VPN-yhteyden"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Voit hallinnoida verkkoa koskettamalla."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index c917749..276be79 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> jours"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> j et <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> j et <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h et <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h et <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min et <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min et <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Sans_titre&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personnel"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Travail"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services payants"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Effectuer des opérations payantes"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vos messages"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9359606..6a6ed88 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> jours"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> j et <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> j et <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h et <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h et <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min et <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min et <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Sans nom&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personnel"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Professionnel"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services payants"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Effectuer des opérations payantes"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vos messages"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 3d5f4df..957e76a 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> दिन"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> दिन <xliff:g id="HOURS">%2$d</xliff:g> घंटे"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> दिन <xliff:g id="HOURS">%2$d</xliff:g> घंटा"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> घंटे"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> घं. <xliff:g id="MINUTES">%2$d</xliff:g> मि."</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> घं. <xliff:g id="MINUTES">%2$d</xliff:g> मि."</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> मिनट"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> मि. <xliff:g id="SECONDS">%2$d</xliff:g> से."</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> मि. <xliff:g id="SECONDS">%2$d</xliff:g> से."</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> सेकंड"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> सेकंड"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;शीर्षक-रहित&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"व्यक्तिगत"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"कार्यालय"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"वे सेवाएं जिन पर आप खर्चा करते हैं"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ऐसे कार्य करें जिससे आपका धन खर्च हो सकता है."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"आपके संदेश"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a195512..e4db3e6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez naslova&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Osobno"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Posao"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usluge koje se plaćaju"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Radite stvari koje će uzrokovati novčane troškove."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše poruke"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 6e82bb8..6130c5e 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> nap"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> nap <xliff:g id="HOURS">%2$d</xliff:g> óra"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> nap <xliff:g id="HOURS">%2$d</xliff:g> óra"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> óra"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> óra <xliff:g id="MINUTES">%2$d</xliff:g> perc"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> óra <xliff:g id="MINUTES">%2$d</xliff:g> perc"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> perc"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> perc <xliff:g id="SECONDS">%2$d</xliff:g> mp"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> perc <xliff:g id="SECONDS">%2$d</xliff:g> mp"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> másodperc"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> másodperc"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Névtelen&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Személyes"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Munkahelyi"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Fizetős szolgáltatások"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Olyan dolgok végrehajtása, amelyek pénzbe kerülnek."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Saját üzenetek"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 12e5fdb..a4a5f48 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> օր"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> օր <xliff:g id="HOURS">%2$d</xliff:g> ժ"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> օր <xliff:g id="HOURS">%2$d</xliff:g> ժ"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ժ"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ժ <xliff:g id="MINUTES">%2$d</xliff:g> ր"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ժ <xliff:g id="MINUTES">%2$d</xliff:g> ր"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> րոպե"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> ր <xliff:g id="SECONDS">%2$d</xliff:g> վ"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> ր <xliff:g id="SECONDS">%2$d</xliff:g> վ"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> վ"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> վ"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Անանուն&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Անձնական"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Աշխատանքային"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Ծառայություններ, որոնց համար կգանձվեք"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Կատարել գործողություններ, որի դիմաց ձեր հաշվից գումար կծախսվի:"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ձեր հաղորդագրությունները"</string>
@@ -409,10 +400,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>
@@ -725,10 +714,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>
@@ -1399,8 +1386,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-in/strings.xml b/core/res/res/values-in/strings.xml
index 2fb00bb..6003a23 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> hari"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> hari <xliff:g id="HOURS">%2$d</xliff:g> jam"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> hari <xliff:g id="HOURS">%2$d</xliff:g> jam"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> jam"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> mnt"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> mnt"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt <xliff:g id="SECONDS">%2$d</xliff:g> dtk"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt <xliff:g id="SECONDS">%2$d</xliff:g> dtk"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> dtk"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> dtk"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Tanpa judul&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Pribadi"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Kantor"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Layanan berbayar"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Lakukan hal yang dapat dikenai biaya."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Pesan Anda"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index af8ed3f..0e83a2f 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> giorni"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> giorno <xliff:g id="HOURS">%2$d</xliff:g> ore"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> giorno <xliff:g id="HOURS">%2$d</xliff:g> ora"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ore"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ora <xliff:g id="MINUTES">%2$d</xliff:g> minuti"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ora <xliff:g id="MINUTES">%2$d</xliff:g> minuto"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minuti"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> minuto <xliff:g id="SECONDS">%2$d</xliff:g> secondi"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> minuto <xliff:g id="SECONDS">%2$d</xliff:g> secondo"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> secondi"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> secondo"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Senza nome&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personale"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Lavoro"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servizi che prevedono un costo"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Svolgono operazioni che possono comportare un costo."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"I tuoi messaggi"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 0157f74..8002d3a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ימים"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"יום <xliff:g id="DAYS">%1$d</xliff:g> ‏<xliff:g id="HOURS">%2$d</xliff:g> שע\'"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"יום <xliff:g id="DAYS">%1$d</xliff:g> שעה <xliff:g id="HOURS">%2$d</xliff:g>"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> שעות"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"שעה <xliff:g id="HOURS">%1$d</xliff:g> ‏<xliff:g id="MINUTES">%2$d</xliff:g> דק\'"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> שעות <xliff:g id="MINUTES">%2$d</xliff:g> דק\'"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> דקות"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"דקה <xliff:g id="MINUTES">%1$d</xliff:g> ‏<xliff:g id="SECONDS">%2$d</xliff:g> שנ\'"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"דקה <xliff:g id="MINUTES">%1$d</xliff:g> שנ\' <xliff:g id="SECONDS">%2$d</xliff:g>"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> שניות"</string>
+    <string name="durationSecond" msgid="985669622276420331">"שנייה <xliff:g id="SECONDS">%1$d</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"‏&gt;ללא כותרת&lt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏מערכת Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"אישי"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"עבודה"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"שירותים שעולים כסף"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ביצוע פעולות שעשויות לעלות לך כסף."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"ההודעות שלך"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a9c5cfb..704b935 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g>日"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g>日<xliff:g id="HOURS">%2$d</xliff:g>時間"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g>日<xliff:g id="HOURS">%2$d</xliff:g>時間"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g>時間"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g>時間<xliff:g id="MINUTES">%2$d</xliff:g>分"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g>時間<xliff:g id="MINUTES">%2$d</xliff:g>分"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g>分"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g>分<xliff:g id="SECONDS">%2$d</xliff:g>秒"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g>分<xliff:g id="SECONDS">%2$d</xliff:g>秒"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g>秒"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g>秒"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;新規&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"プライベート"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"職場"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"料金の発生するサービス"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"料金発生の可能性がある操作を実行します。"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"送受信したメッセージ"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index e5ec81b..0c179c0 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> დღე"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> დღე <xliff:g id="HOURS">%2$d</xliff:g> სთ"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> დღე <xliff:g id="HOURS">%2$d</xliff:g> სთ"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> სთ"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> სთ <xliff:g id="MINUTES">%2$d</xliff:g> წთ"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> სთ <xliff:g id="MINUTES">%2$d</xliff:g> წთ"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> წთ"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> წთ <xliff:g id="SECONDS">%2$d</xliff:g> წმ"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> წთ <xliff:g id="SECONDS">%2$d</xliff:g> წმ"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> წმ"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> წმ"</string>
     <string name="untitled" msgid="4638956954852782576">"უსათაურო"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-ის სისტემა"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"პირადი"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"სამსახური"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"სერვისები, რომელშიც ფულის გადახდა გიწევთ"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ისეთი აქტივობების განხორციელება, რომლებშიც ფულის გადახდა მოგიწევთ."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"თქვენი შეტყობინებები"</string>
@@ -409,10 +400,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>
@@ -725,10 +714,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>
@@ -1399,8 +1386,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-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index e9a021c..4d6f0a3 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ថ្ងៃ"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ថ្ងៃ <xliff:g id="HOURS">%2$d</xliff:g> ម៉ោង"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ថ្ងៃ <xliff:g id="HOURS">%2$d</xliff:g> ម៉ោង"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ម៉ោង"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ម៉ោង <xliff:g id="MINUTES">%2$d</xliff:g> នាទី"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ម៉ោង <xliff:g id="MINUTES">%2$d</xliff:g> នាទី"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> នាទី"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g>នាទី <xliff:g id="SECONDS">%2$d</xliff:g>វិនាទី"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g>នាទី <xliff:g id="SECONDS">%2$d</xliff:g>វិនាទី"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> វិនាទី"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> វិនាទី"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;គ្មាន​ចំណង​ជើង&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ប្រព័ន្ធ​​ Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"ផ្ទាល់ខ្លួន"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"កន្លែង​ធ្វើ​ការ"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"សេវាកម្ម​ដែល​កាត់​លុយ​របស់​អ្នក"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ធ្វើ​អ្វី​ដែល​អាច​កាត់​លុយ​របស់​អ្នក។"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"សារ​របស់​អ្នក"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 7c6feba..310b1f0 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g>일"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g>일 <xliff:g id="HOURS">%2$d</xliff:g>시간"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g>일 <xliff:g id="HOURS">%2$d</xliff:g>시간"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g>시간"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g>시간 <xliff:g id="MINUTES">%2$d</xliff:g>분"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g>시간 <xliff:g id="MINUTES">%2$d</xliff:g>분"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g>분"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g>분 <xliff:g id="SECONDS">%2$d</xliff:g>초"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g>분 <xliff:g id="SECONDS">%2$d</xliff:g>초"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g>초"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g>초"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;제목 없음&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"개인"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"직장"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"요금이 부과되는 서비스"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"요금이 부과될 수 있는 작업을 수행할 수 있도록 합니다."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"메시지"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index b31fbff..08ba7e1 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ມື້"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ມື້ <xliff:g id="HOURS">%2$d</xliff:g> ຊມ"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ມື້ <xliff:g id="HOURS">%2$d</xliff:g> ຊມ"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ຊມ"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ຊມ <xliff:g id="MINUTES">%2$d</xliff:g> ນທ"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ຊມ <xliff:g id="MINUTES">%2$d</xliff:g> ນທ"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> ນທ"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> ນທ <xliff:g id="SECONDS">%2$d</xliff:g> ວິ"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> ນທ <xliff:g id="SECONDS">%2$d</xliff:g> ວິ"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ວິ"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ວິ"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;ບໍ່ມີຊື່&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"​ສ່ວນ​ໂຕ"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"​ບ່ອນ​ເຮັດ​ວຽກ"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"ບໍລິການທີ່ເຮັດໃຫ້ທ່ານເສຍເງິນ"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ເຮັດສິ່ງທີ່ທ່ານຕ້ອງເສຍຄ່າໃຊ້ຈ່າຍ."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"ຂໍ້ຄວາມຂອງທ່ານ"</string>
@@ -409,10 +400,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>
@@ -725,10 +714,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>
@@ -1399,8 +1386,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-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 62b6c7a..7250f02 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d."</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> val."</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> val."</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> val."</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> val. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> val. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min."</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> sek."</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> sek."</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sek."</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sek."</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Be pavadinimo&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
     <string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Asmeninė"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Darbo"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Paslaugos, už kurias mokėjote"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Atlikite mokamus veiksmus."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Jūsų pranešimai"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index b803e61..4c48278 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d."</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez nosaukuma&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Pārsniedz"</string>
     <string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personisks"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Darba"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksas pakalpojumi"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Veikt darbības, par kurām, iespējams, būs jāmaksā."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Jūsu ziņojumi"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index cc0fa7f..c609745 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> өдөр"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> өдөр <xliff:g id="HOURS">%2$d</xliff:g> цаг"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> өдөр <xliff:g id="HOURS">%2$d</xliff:g> цаг"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> цаг"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> цаг <xliff:g id="MINUTES">%2$d</xliff:g> минут"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> цаг <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> мин"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> секунд"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Гарчиггүй&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Андройд систем"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Хувийн"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Ажил"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Танаас төлбөр авдаг үйлчилгээнүүд"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Таны төлбөрт оруулах зүйлийг хийх."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Таны мессеж"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 53c9b94..ea9ffb3 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> hari"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> hari <xliff:g id="HOURS">%2$d</xliff:g> jam"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> hari <xliff:g id="HOURS">%2$d</xliff:g> jam"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> jam"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minit"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> saat"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> saat"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> saat"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> saat"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Tidak bertajuk&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,10 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
+    <!-- no translation found for user_owner_label (2804351898001038951) -->
+    <skip />
+    <!-- no translation found for managed_profile_label (6260850669674791528) -->
+    <skip />
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Perkhidmatan yang anda perlu bayar"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Melakukan perkara yang boleh mengenakan bayaran kepada anda."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesej anda"</string>
@@ -409,10 +402,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan Vpn. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"terikat pada kertas dinding"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kertas dinding. Tidak sekali-kali diperlukan untuk apl biasa."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"terikat kepada interaksi suara"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan interaksi suara. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"terikat kepada paparan jauh"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi paparan jauh. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"terikat kepada perkhidmatan widget"</string>
@@ -725,10 +716,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Membenarkan apl untuk mendapatkan semula, memeriksa dan memadam bersih pemberitahuan, termasuk yang disiarkan oleh apl lain."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ikat kepada perkhidmatan pendengar pemberitahuan"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan pendengar pemberitahuan. Tidak sekali-kali diperlukan untuk apl biasa."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"terikat kepada perkhidmatan pembekal keadaan"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan pembekal keadaan. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gunakan apl konfigurasi yang disediakan oleh pembawa"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Membenarkan pemegang menggunakan apl konfigurasi yang diberikan oleh pembawa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"dengar pemerhatian mengenai keadaan rangkaian"</string>
@@ -1399,8 +1388,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Kertas dinding"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</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">"Pembekal keadaan"</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 mengurus rangkaian."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index a67cb28..16c5352 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dager"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> t"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> t"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> t"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> t <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> t <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sek"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sek"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Uten navn&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personlig"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Jobb"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Betaltjenester"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Gjøre ting som kan koste deg penger."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Meldinger"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 3b2391f..c19adf2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dagen"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> uur"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minuten"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> seconden"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> seconde"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Zonder titel&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Persoonlijk"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Werk"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services waarvoor u moet betalen"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Activiteiten uitvoeren waarvoor kosten in rekening kunnen worden gebracht."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Uw berichten"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b80c1fd..949fea8 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dni"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dzień <xliff:g id="HOURS">%2$d</xliff:g> godz."</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dzień <xliff:g id="HOURS">%2$d</xliff:g> godz."</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> godz."</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> godz. <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> godz. <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez nazwy&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
     <string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Osobiste"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Praca"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usługi płatne"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Wykonywanie czynności, za które pobierana jest opłata."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Twoje wiadomości"</string>
@@ -737,7 +728,7 @@
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Przy odblokowywaniu ekranu monitoruj, ile razy wpisano nieprawidłowe hasło i blokuj tablet lub usuń z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło i blokuje telefon lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło, i blokuje telefon lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy"</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"Zmień hasło odblokowania ekranu"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"Zmienianie hasła odblokowania ekranu"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Zablokuj ekran"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 668f9ef..ecec099 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dias"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> horas"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min."</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> seg."</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> seg."</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> seg."</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> seg."</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Sem nome&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Pessoal"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Trabalho"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que implicam pagamento"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Efetuar ações que implicam pagamento."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"As suas mensagens"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index db493e0..93107ca 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dias"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> horas"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <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>
@@ -199,6 +188,10 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+    <!-- no translation found for user_owner_label (2804351898001038951) -->
+    <skip />
+    <!-- no translation found for managed_profile_label (6260850669674791528) -->
+    <skip />
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que geram gastos"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Faça coisas que podem custar dinheiro."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Suas mensagens"</string>
@@ -409,10 +402,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite que seu proprietário sujeite a interface de alto nível de um serviço de VPN. Nunca deve ser necessário para aplicativos normais."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sujeitar-se a um plano de fundo"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite que o proprietário utilize interface de nível superior de um plano de fundo. Nunca deve ser necessário para aplicativos normais."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"associar a um interagente de voz"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite que o proprietário use a interface de nível superior de um serviço de interação de voz. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"usar uma tela remota"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite que o proprietário use a interface de nível superior de uma tela remota. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sujeitar-se a um serviço de widget"</string>
@@ -725,10 +716,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que o aplicativo recupere, examine e limpe notificações, inclusive as postadas por outros aplicativos."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"sujeitar a um serviço ouvinte de notificações"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite que o proprietário sujeite a interface de nível superior a um serviço ouvinte de notificações. Não deve ser necessário para aplicativos comuns."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"associar a um serviço provedor de condições"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite que o proprietário use a interface de nível superior de um serviço provedor de condições. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invocar o aplicativo de configuração fornecido pela operadora"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite que o proprietário invoque o aplicativo de configuração fornecido pela operadora. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"detectar observações nas condições da rede"</string>
@@ -1399,8 +1388,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Plano de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar plano de fundo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ouvinte de notificações"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provedor de condições"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerenciar a rede."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 3103b1f..6bdaee5 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -246,6 +246,10 @@
     <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modus segirà"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
+    <!-- no translation found for user_owner_label (2804351898001038951) -->
+    <skip />
+    <!-- no translation found for managed_profile_label (6260850669674791528) -->
+    <skip />
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servetschs che custan"</string>
     <!-- no translation found for permgroupdesc_costMoney (3293301903409869495) -->
     <skip />
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 3ee0b8a..568e093 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> (de) zile"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> zile <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> zi <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> (de) min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sec"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sec"</string>
     <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>
@@ -199,6 +188,10 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
+    <!-- no translation found for user_owner_label (2804351898001038951) -->
+    <skip />
+    <!-- no translation found for managed_profile_label (6260850669674791528) -->
+    <skip />
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicii cu plată"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Efectuează acţiuni care sunt cu plată."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajele dvs."</string>
@@ -409,10 +402,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu VPN. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"conectare la o imagine de fundal"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unei imagini de fundal. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"conectare la un serviciu de interacțiune vocală"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu de interacțiune vocală. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"conectare la un ecran la distanță"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite proprietarului să se conecteze la interfața de nivel superior a unui ecran la distanță. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"conectare la un serviciu widget"</string>
@@ -725,10 +716,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite aplicației să recupereze, să examineze și să șteargă notificări, inclusiv pe cele postate de alte aplicații."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"conectare la un serviciu de citire a notificărilor"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu de citire a notificărilor. În mod normal aplicațiile nu ar trebui să aibă nevoie de această permisiune."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"conectare la un serviciu furnizor de condiții"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu furnizor de condiții. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"apelarea aplicației de configurare furnizată de operator"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite proprietarului să apeleze aplicația de configurare furnizată de operator. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ascultă observații despre starea rețelei"</string>
@@ -1399,8 +1388,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagine de fundal"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Modificaţi imaginea de fundal"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviciu de citire a notificărilor"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Furnizor de condiții"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Atingeţi pentru a gestiona reţeaua."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 8c7a566..8a0141a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дн."</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> день <xliff:g id="HOURS">%2$d</xliff:g> ч."</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> день <xliff:g id="HOURS">%2$d</xliff:g> ч."</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ч."</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ч. <xliff:g id="MINUTES">%2$d</xliff:g> мин."</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ч. <xliff:g id="MINUTES">%2$d</xliff:g> мин."</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> мин."</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин. <xliff:g id="SECONDS">%2$d</xliff:g> с."</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин. <xliff:g id="SECONDS">%2$d</xliff:g> с."</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> с."</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> с."</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Без названия&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Личные данные"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Работа"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Платные услуги"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Приложение сможет использовать платные услуги."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Сообщения"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c96c661..08e4c08 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d."</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> hod."</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> hod."</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> hod."</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> hod. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> hod. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min."</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez mena&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Osobné"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Práca"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Spoplatnené služby"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Vykonávanie činností, ktoré vás môžu stáť peniaze."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše správy"</string>
@@ -409,10 +400,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby VPN. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"väzba na tapetu"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania tapety. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
-    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
-    <skip />
-    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
-    <skip />
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"viazanie na hlasovú interakciu"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby hlasovej interakcie. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"viazať na vzdialený displej"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania vzdialeného displeja. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"viazať sa k službe miniaplikácie"</string>
@@ -725,10 +714,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikácii načítať, zobrazovať a mazať upozornenia vrátane tých, ktoré boli uverejnené inými aplikáciami."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"naviazanie sa na službu na počúvanie upozornení"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Umožňuje držiteľovi naviazať sa na najvyššiu úroveň služby na počúvanie upozornení. Bežné aplikácie by toto nastavenie nemali nikdy požadovať."</string>
-    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
-    <skip />
-    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
-    <skip />
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"viazanie na službu poskytovateľa podmienky"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby poskytovateľa podmienky. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"vyvolanie aplikácie pre konfiguráciu poskytnutú operátorom"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Umožňuje držiteľovi vyvolať aplikáciu pre konfiguráciu poskytnutú operátorom. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"zachytávať informácie o stave siete"</string>
@@ -1399,8 +1386,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmeniť tapetu"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Aplikácia na počúvanie upozornení"</string>
-    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
-    <skip />
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Poskytovateľ podmienky"</string>
     <string name="vpn_title" msgid="19615213552042827">"Sieť VPN je aktivovaná"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikáciu <xliff:g id="APP">%s</xliff:g> aktivovala sieť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykom môžete spravovať sieť."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ef5d872..dfa767b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"Št. dni: <xliff:g id="DAYS">%1$d</xliff:g>"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dan <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dan <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Brez naslova&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Osebno"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Služba"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Plačljive storitve"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Dovolite stvari, za katere bo morda treba plačati."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaša sporočila"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b87bd89..fb65c02 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дана"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> дан <xliff:g id="HOURS">%2$d</xliff:g> с"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> дан <xliff:g id="HOURS">%2$d</xliff:g> с"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> с"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> с <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> с <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> мин"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Без наслова&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Лично"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Посао"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуге које се плаћају"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Покреће радње које могу да се плаћају."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Поруке"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 9b4dae3..ea713a6 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dagar"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> tim"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> tim"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> timmar"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> tim <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> tim <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minuter"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sekunder"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sekund"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Okänd&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personligt"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Arbetet"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjänster som kostar pengar"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Göra saker som kan kosta pengar."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Dina meddelanden"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 558cae2..8c77050 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"Siku <xliff:g id="DAYS">%1$d</xliff:g>"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"Siku <xliff:g id="DAYS">%1$d</xliff:g> saa <xliff:g id="HOURS">%2$d</xliff:g>"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"Siku <xliff:g id="DAYS">%1$d</xliff:g> saa <xliff:g id="HOURS">%2$d</xliff:g>"</string>
+    <string name="durationHours" msgid="4266858287167358988">"Saa <xliff:g id="HOURS">%1$d</xliff:g>"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"Saa <xliff:g id="HOURS">%1$d</xliff:g> dak <xliff:g id="MINUTES">%2$d</xliff:g>"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"Saa <xliff:g id="HOURS">%1$d</xliff:g> dak <xliff:g id="MINUTES">%2$d</xliff:g>"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"Dakika <xliff:g id="MINUTES">%1$d</xliff:g>"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"Dak <xliff:g id="MINUTES">%1$d</xliff:g> sek <xliff:g id="SECONDS">%2$d</xliff:g>"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"Dak <xliff:g id="MINUTES">%1$d</xliff:g> sek <xliff:g id="SECONDS">%2$d</xliff:g>"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"Sekunde <xliff:g id="SECONDS">%1$d</xliff:g>"</string>
+    <string name="durationSecond" msgid="985669622276420331">"Sekunde <xliff:g id="SECONDS">%1$d</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Haina jina&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Binafsi"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Kazini"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Huduma ambazo zinakugharimu pesa"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Fanya mambo ambayo yanaweza kukugharimu pesa."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ujumbe wako"</string>
@@ -409,8 +400,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>
-    <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_bindVoiceInteraction" msgid="5334852580713715068">"bandika kwenye mwingiliano wa sauti"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Humruhusu mmiliki kubandika kwenye kiolesura cha hali ya juu cha huduma ya muingiliano wa sauti. Isihitajike kamwe 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>
@@ -723,8 +714,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>
-    <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_bindConditionProviderService" msgid="1180107672332704641">"bandika kwenye huduma ya mtoa masharti"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Humruhusu mmiliki kubandika kwenye kiolesura cha kiwango cha juu cha huduma ya mtoa masharti. Isihitajike kamwe 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>
@@ -1395,7 +1386,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>
-    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Mtoa hali"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Mtoa masharti"</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 826fa64..7f0cf61 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> วัน"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> วัน <xliff:g id="HOURS">%2$d</xliff:g> ชม."</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> วัน <xliff:g id="HOURS">%2$d</xliff:g> ชม."</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ชม."</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ชม. <xliff:g id="MINUTES">%2$d</xliff:g> นาที"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ชม. <xliff:g id="MINUTES">%2$d</xliff:g> นาที"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> นาที"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> นาที <xliff:g id="SECONDS">%2$d</xliff:g> วิ."</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> นาที <xliff:g id="SECONDS">%2$d</xliff:g> วิ."</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> วินาที"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> วินาที"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;ไม่มีชื่อ&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"ส่วนตัว"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"ที่ทำงาน"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"บริการที่ต้องเสียค่าใช้จ่าย"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ทำสิ่งที่คุณต้องเสียค่าใช้จ่าย"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"ข้อความของคุณ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 6e50517..969b651 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> (na) araw"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hr"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hr"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> (na) oras"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> oras <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> oras <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> (na) min"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> seg"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> seg"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> (na) seg"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> (na) seg"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Walang pamagat&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Trabaho"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Mga serbisyong ginagastusan mo"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Gumawa ng mga bagay na magpapagastos sa iyo."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Iyong mga mensahe"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index bd2f926..6e6151f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> gün"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> gün <xliff:g id="HOURS">%2$d</xliff:g> sa."</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> gün <xliff:g id="HOURS">%2$d</xliff:g> sa."</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> sa."</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> sa. <xliff:g id="MINUTES">%2$d</xliff:g> dk."</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> sa. <xliff:g id="MINUTES">%2$d</xliff:g> dk."</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> dk."</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> dk. <xliff:g id="SECONDS">%2$d</xliff:g> sn."</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> dk. <xliff:g id="SECONDS">%2$d</xliff:g> sn."</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sn."</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sn."</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Adsız&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Kişisel"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"İş"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Size maliyet getiren hizmetler"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Size maliyet getirebilecek işlemler yapma."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajlarınız"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index d01c5776..63fdd15 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дн."</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> день <xliff:g id="HOURS">%2$d</xliff:g> год"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> дн. <xliff:g id="HOURS">%2$d</xliff:g> год"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> год"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> год <xliff:g id="MINUTES">%2$d</xliff:g> хв"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> год <xliff:g id="MINUTES">%2$d</xliff:g> хв"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> хв"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> хв <xliff:g id="SECONDS">%2$d</xliff:g> с"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> хв <xliff:g id="SECONDS">%2$d</xliff:g> с"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> с"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> с"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Без назви&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Особистий профіль"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Службовий профіль"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Служби, які потребують оплати"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Виконувати дії, які потребують оплати."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ваші повідомл."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 24b2db5..545b92e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ngày"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ngày <xliff:g id="HOURS">%2$d</xliff:g> giờ"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ngày <xliff:g id="HOURS">%2$d</xliff:g> giờ"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> giờ"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> giờ <xliff:g id="MINUTES">%2$d</xliff:g> phút"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> giờ <xliff:g id="MINUTES">%2$d</xliff:g> phút"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> phút"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> phút <xliff:g id="SECONDS">%2$d</xliff:g> giây"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> phút <xliff:g id="SECONDS">%2$d</xliff:g> giây"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> giây"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> giây"</string>
     <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>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Cá nhân"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Cơ quan"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Dịch vụ tính tiền của bạn"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Thực hiện những tác vụ mà bạn có thể phải trả tiền."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Tin nhắn của bạn"</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index e71fa4a..44e258d 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -32,7 +32,7 @@
     <dimen name="config_viewConfigurationTouchSlop">4dp</dimen>
 
     <!-- Minimum velocity to initiate a fling, as measured in dips per second. -->
-    <dimen name="config_viewMinFlingVelocity">50dp</dimen>
+    <dimen name="config_viewMinFlingVelocity">500dp</dimen>
 
     <!-- Maximum velocity to initiate a fling, as measured in dips per second. -->
     <dimen name="config_viewMaxFlingVelocity">8000dp</dimen>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 9297e3a..793e5bf 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g>天"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g>天<xliff:g id="HOURS">%2$d</xliff:g>小时"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g>天<xliff:g id="HOURS">%2$d</xliff:g>小时"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g>小时"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g>小时<xliff:g id="MINUTES">%2$d</xliff:g>分钟"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g>小时<xliff:g id="MINUTES">%2$d</xliff:g>分钟"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g>分钟"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g>分钟<xliff:g id="SECONDS">%2$d</xliff:g>秒"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g>分钟<xliff:g id="SECONDS">%2$d</xliff:g>秒"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g>秒"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g>秒"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,10 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
+    <!-- no translation found for user_owner_label (2804351898001038951) -->
+    <skip />
+    <!-- no translation found for managed_profile_label (6260850669674791528) -->
+    <skip />
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要您付费的服务"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"执行可能需要您付费的操作。"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"您的信息"</string>
@@ -409,10 +402,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>
@@ -725,10 +716,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>
@@ -1399,8 +1388,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-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 1c8cfe8..fdd02a7 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> 天"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> 天 <xliff:g id="HOURS">%2$d</xliff:g> 小時"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> 天 <xliff:g id="HOURS">%2$d</xliff:g> 小時"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> 小時"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> 小時 <xliff:g id="MINUTES">%2$d</xliff:g> 分鐘"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> 小時 <xliff:g id="MINUTES">%2$d</xliff:g> 分鐘"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘 <xliff:g id="SECONDS">%2$d</xliff:g> 秒"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘 <xliff:g id="SECONDS">%2$d</xliff:g> 秒"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> 秒"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> 秒"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"個人"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"公司"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"付費服務"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"執行需付費的操作或服務。"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"您的訊息"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 05e0894..547ca27 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> 天"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> 天 <xliff:g id="HOURS">%2$d</xliff:g> 小時"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> 天 <xliff:g id="HOURS">%2$d</xliff:g> 小時"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> 小時"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> 小時 <xliff:g id="MINUTES">%2$d</xliff:g> 分鐘"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> 小時 <xliff:g id="MINUTES">%2$d</xliff:g> 分鐘"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘 <xliff:g id="SECONDS">%2$d</xliff:g> 秒"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘 <xliff:g id="SECONDS">%2$d</xliff:g> 秒"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> 秒"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> 秒"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"超過 999"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"個人"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"公司"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要額外費用的服務。"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"執行需付費的作業或服務。"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"您的簡訊"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 9c8542e..58fdb1c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -27,28 +27,17 @@
     <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="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> izinsuku"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> usuku <xliff:g id="HOURS">%2$d</xliff:g> amahora"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> usuku <xliff:g id="HOURS">%2$d</xliff:g> ihora"</string>
+    <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> amahora"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ihora <xliff:g id="MINUTES">%2$d</xliff:g> amaminithi"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ihora <xliff:g id="MINUTES">%2$d</xliff:g> iminithi"</string>
+    <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> amaminithi"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> iminithi <xliff:g id="SECONDS">%2$d</xliff:g> amasekhondi"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> iminithi <xliff:g id="SECONDS">%2$d</xliff:g> isekhondi"</string>
+    <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> amasekhondi"</string>
+    <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> isekhondi"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Akunasihloko&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
+    <string name="user_owner_label" msgid="2804351898001038951">"Okomuntu siqu"</string>
+    <string name="managed_profile_label" msgid="6260850669674791528">"Umsebenzi"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Amasevisi abiza imali"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Yenza izinto ezingakudla imali."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Imiyalezo yakho"</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 305ba28..f01f10e 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -348,43 +348,4 @@
         <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 e07ebd4..0326e18 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -721,6 +721,7 @@
         <attr name="actionBarTabBarStyle" format="reference" />
         <attr name="actionBarTabTextStyle" format="reference" />
         <attr name="actionOverflowButtonStyle" format="reference" />
+        <attr name="actionOverflowMenuStyle" format="reference" />
         <!-- Reference to a style for the Action Bar -->
         <attr name="actionBarStyle" format="reference" />
         <!-- Reference to a style for the split Action Bar. This style
@@ -3803,6 +3804,7 @@
     <declare-styleable name="PopupWindow">
         <attr name="popupBackground" format="reference|color" />
         <attr name="popupAnimationStyle" format="reference" />
+        <attr name="overlapAnchor" format="boolean" />
     </declare-styleable>
     <declare-styleable name="ViewAnimator">
         <!-- Identifier for the animation to use when a view is shown. -->
@@ -5810,6 +5812,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" />
@@ -5951,11 +5956,12 @@
             <flag name="vertical" value="0x2" />
         </attr>
         <!-- Optional parameter which indicates where this widget can be shown,
-             ie. home screen, keyguard or both.
-             resized. Supports combined values using | operator. -->
+             ie. home screen, keyguard, recents or any combination thereof.
+             Supports combined values using | operator. -->
         <attr name="widgetCategory" format="integer">
             <flag name="home_screen" value="0x1" />
             <flag name="keyguard" value="0x2" />
+            <flag name="recents" value="0x4" />
         </attr>
     </declare-styleable>
 
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 441fd94..761170d 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -71,11 +71,7 @@
     <drawable name="editbox_dropdown_dark_frame">@drawable/editbox_dropdown_background_dark</drawable>
     <drawable name="editbox_dropdown_light_frame">@drawable/editbox_dropdown_background</drawable>
 
-    <drawable name="dialog_holo_dark_frame">@drawable/dialog_full_holo_dark</drawable>
-    <drawable name="dialog_holo_light_frame">@drawable/dialog_full_holo_light</drawable>
-
     <drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
-    <drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable>
     <color name="input_method_navigation_guard">#ff000000</color>
 
     <!-- For date picker widget -->
@@ -122,76 +118,8 @@
     <!-- FaceLock -->
     <color name="facelock_spotlight_mask">#CC000000</color>
 
-    <!-- For holo theme -->
-    <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
-    <drawable name="screen_background_holo_dark">#ff000000</drawable>
-    <color name="background_holo_dark">#ff000000</color>
-    <color name="background_holo_light">#fff3f3f3</color>
-    <color name="bright_foreground_holo_dark">@android:color/background_holo_light</color>
-    <color name="bright_foreground_holo_light">@android:color/background_holo_dark</color>
-    <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
-    <color name="bright_foreground_disabled_holo_light">#ffb2b2b2</color>
-    <color name="bright_foreground_inverse_holo_dark">@android:color/bright_foreground_holo_light</color>
-    <color name="bright_foreground_inverse_holo_light">@android:color/bright_foreground_holo_dark</color>
-    <color name="dim_foreground_holo_dark">#bebebe</color>
-    <color name="dim_foreground_disabled_holo_dark">#80bebebe</color>
-    <color name="dim_foreground_inverse_holo_dark">#323232</color>
-    <color name="dim_foreground_inverse_disabled_holo_dark">#80323232</color>
-    <color name="hint_foreground_holo_dark">#808080</color>
-    <color name="dim_foreground_holo_light">#323232</color>
-    <color name="dim_foreground_disabled_holo_light">#80323232</color>
-    <color name="dim_foreground_inverse_holo_light">#bebebe</color>
-    <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
-    <color name="hint_foreground_holo_light">#808080</color>
-    <color name="highlighted_text_holo_dark">#6633b5e5</color>
-    <color name="highlighted_text_holo_light">#6633b5e5</color>
-    <color name="link_text_holo_dark">#5c5cff</color>
-    <color name="link_text_holo_light">#0000ee</color>
-
     <color name="micro_text_light">#434343</color>
 
-    <!-- Group buttons -->
-    <eat-comment />
-    <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
-    <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
-
-    <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
-    <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
-
-    <!-- Highlight colors for the legacy themes -->
-    <eat-comment />
-    <color name="legacy_pressed_highlight">#fffeaa0c</color>
-    <color name="legacy_selected_highlight">#fff17a0a</color>
-    <color name="legacy_long_pressed_highlight">#ffffffff</color>
-
-    <!-- General purpose colors for Holo-themed elements -->
-    <eat-comment />
-
-    <!-- A light Holo shade of blue -->
-    <color name="holo_blue_light">#ff33b5e5</color>
-    <!-- A light Holo shade of gray -->
-    <color name="holo_gray_light">#33999999</color>
-    <!-- A light Holo shade of green -->
-    <color name="holo_green_light">#ff99cc00</color>
-    <!-- A light Holo shade of red -->
-    <color name="holo_red_light">#ffff4444</color>
-    <!-- A dark Holo shade of blue -->
-    <color name="holo_blue_dark">#ff0099cc</color>
-    <!-- A dark Holo shade of green -->
-    <color name="holo_green_dark">#ff669900</color>
-    <!-- A dark Holo shade of red -->
-    <color name="holo_red_dark">#ffcc0000</color>
-    <!-- A Holo shade of purple -->
-    <color name="holo_purple">#ffaa66cc</color>
-    <!-- A light Holo shade of orange -->
-    <color name="holo_orange_light">#ffffbb33</color>
-    <!-- A dark Holo shade of orange -->
-    <color name="holo_orange_dark">#ffff8800</color>
-    <!-- A really bright Holo shade of blue -->
-    <color name="holo_blue_bright">#ff00ddff</color>
-    <!-- A really bright Holo shade of gray -->
-    <color name="holo_gray_bright">#33CCCCCC</color>
-
     <drawable name="notification_template_icon_bg">#3333B5E5</drawable>
     <drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
 
@@ -206,21 +134,5 @@
 
     <color name="accessibility_focus_highlight">#80ffff00</color>
 
-    <!-- New TimePicker colors -->
-    <color name="timepicker_default_background_holo_light">@android:color/white</color>
-    <color name="timepicker_default_background_holo_dark">#ff303030</color>
-
-    <color name="timepicker_default_text_color_holo_light">#8c8c8c</color>
-    <color name="timepicker_default_text_color_holo_dark">@android:color/white</color>
-
-    <color name="timepicker_default_disabled_color_holo_light">#7f000000</color>
-    <color name="timepicker_default_disabled_color_holo_dark">#7f08c8c8</color>
-
-    <color name="timepicker_default_ampm_selected_background_color_holo_light">@android:color/holo_blue_light</color>
-    <color name="timepicker_default_ampm_selected_background_color_holo_dark">@android:color/holo_blue_light</color>
-
-    <color name="timepicker_default_ampm_unselected_background_color_holo_light">@android:color/white</color>
-    <color name="timepicker_default_ampm_unselected_background_color_holo_dark">@android:color/transparent</color>
-
 </resources>
 
diff --git a/core/res/res/values/colors_holo.xml b/core/res/res/values/colors_holo.xml
new file mode 100644
index 0000000..d1f4e38
--- /dev/null
+++ b/core/res/res/values/colors_holo.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Colors specific to Holo themes. -->
+<resources>
+
+    <drawable name="dialog_holo_dark_frame">@drawable/dialog_full_holo_dark</drawable>
+    <drawable name="dialog_holo_light_frame">@drawable/dialog_full_holo_light</drawable>
+    <drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable>
+
+    <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
+    <drawable name="screen_background_holo_dark">#ff000000</drawable>
+
+    <color name="background_holo_dark">#ff000000</color>
+    <color name="background_holo_light">#fff3f3f3</color>
+    <color name="bright_foreground_holo_dark">@color/background_holo_light</color>
+    <color name="bright_foreground_holo_light">@color/background_holo_dark</color>
+    <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
+    <color name="bright_foreground_disabled_holo_light">#ffb2b2b2</color>
+    <color name="bright_foreground_inverse_holo_dark">@color/bright_foreground_holo_light</color>
+    <color name="bright_foreground_inverse_holo_light">@color/bright_foreground_holo_dark</color>
+    <color name="dim_foreground_holo_dark">#bebebe</color>
+    <color name="dim_foreground_disabled_holo_dark">#80bebebe</color>
+    <color name="dim_foreground_inverse_holo_dark">#323232</color>
+    <color name="dim_foreground_inverse_disabled_holo_dark">#80323232</color>
+    <color name="hint_foreground_holo_dark">#808080</color>
+    <color name="dim_foreground_holo_light">#323232</color>
+    <color name="dim_foreground_disabled_holo_light">#80323232</color>
+    <color name="dim_foreground_inverse_holo_light">#bebebe</color>
+    <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
+    <color name="hint_foreground_holo_light">#808080</color>
+    <color name="highlighted_text_holo_dark">#6633b5e5</color>
+    <color name="highlighted_text_holo_light">#6633b5e5</color>
+    <color name="link_text_holo_dark">#5c5cff</color>
+    <color name="link_text_holo_light">#0000ee</color>
+
+    <!-- General purpose colors for Holo-themed elements -->
+    <eat-comment />
+
+    <!-- A light Holo shade of blue -->
+    <color name="holo_blue_light">#ff33b5e5</color>
+    <!-- A light Holo shade of gray -->
+    <color name="holo_gray_light">#33999999</color>
+    <!-- A light Holo shade of green -->
+    <color name="holo_green_light">#ff99cc00</color>
+    <!-- A light Holo shade of red -->
+    <color name="holo_red_light">#ffff4444</color>
+    <!-- A dark Holo shade of blue -->
+    <color name="holo_blue_dark">#ff0099cc</color>
+    <!-- A dark Holo shade of green -->
+    <color name="holo_green_dark">#ff669900</color>
+    <!-- A dark Holo shade of red -->
+    <color name="holo_red_dark">#ffcc0000</color>
+    <!-- A Holo shade of purple -->
+    <color name="holo_purple">#ffaa66cc</color>
+    <!-- A light Holo shade of orange -->
+    <color name="holo_orange_light">#ffffbb33</color>
+    <!-- A dark Holo shade of orange -->
+    <color name="holo_orange_dark">#ffff8800</color>
+    <!-- A really bright Holo shade of blue -->
+    <color name="holo_blue_bright">#ff00ddff</color>
+    <!-- A really bright Holo shade of gray -->
+    <color name="holo_gray_bright">#33CCCCCC</color>
+
+    <!-- Forward compatibility for Quantum-style theme colors -->
+    <eat-comment />
+
+    <color name="holo_primary_dark">#ff000000</color>
+    <color name="holo_primary">#ffe6e6e6</color>
+    <color name="holo_primary_light">#ffffffff</color>
+    <color name="holo_control_activated">@color/holo_blue_light</color>
+    <color name="holo_control_normal">#39cccccc</color>
+    <color name="holo_button_pressed">#59f0f0f0</color>
+    <color name="holo_button_normal">#bd292f34</color>
+
+    <color name="holo_light_primary_dark">#ff000000</color>
+    <color name="holo_light_primary">#ffe6e6e6</color>
+    <color name="holo_light_primary_light">#ffffffff</color>
+    <color name="holo_light_control_activated">@color/holo_control_activated</color>
+    <color name="holo_light_control_normal">#dacccccc</color>
+    <color name="holo_light_button_pressed">#66666666</color>
+    <color name="holo_light_button_normal">#b3cccccc</color>
+
+    <!-- Group buttons -->
+    <eat-comment />
+
+    <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
+    <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
+
+    <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
+    <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
+
+    <!-- Time picker -->
+    <eat-comment />
+
+    <color name="timepicker_default_background_holo_light">@color/white</color>
+    <color name="timepicker_default_background_holo_dark">#ff303030</color>
+
+    <color name="timepicker_default_text_color_holo_light">#8c8c8c</color>
+    <color name="timepicker_default_text_color_holo_dark">@color/white</color>
+
+    <color name="timepicker_default_disabled_color_holo_light">#7f000000</color>
+    <color name="timepicker_default_disabled_color_holo_dark">#7f08c8c8</color>
+
+    <color name="timepicker_default_ampm_selected_background_color_holo_light">@color/holo_blue_light</color>
+    <color name="timepicker_default_ampm_selected_background_color_holo_dark">@color/holo_blue_light</color>
+
+    <color name="timepicker_default_ampm_unselected_background_color_holo_light">@color/white</color>
+    <color name="timepicker_default_ampm_unselected_background_color_holo_dark">@color/transparent</color>
+</resources>
diff --git a/core/res/res/values/colors_legacy.xml b/core/res/res/values/colors_legacy.xml
new file mode 100644
index 0000000..48d4b42
--- /dev/null
+++ b/core/res/res/values/colors_legacy.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Colors specific to pre-Holo themes. -->
+<resources>
+
+    <!-- Highlight colors for the legacy themes -->
+    <eat-comment />
+
+    <color name="legacy_pressed_highlight">#fffeaa0c</color>
+    <color name="legacy_selected_highlight">#fff17a0a</color>
+    <color name="legacy_long_pressed_highlight">#ffffffff</color>
+
+    <!-- Forward compatibility for Quantum-style theme colors -->
+    <eat-comment />
+
+    <color name="legacy_primary_dark">#ff000000</color>
+    <color name="legacy_primary">#ffe6e6e6</color>
+    <color name="legacy_primary_light">#ffffffff</color>
+    <color name="legacy_control_activated">#ff90df25</color>
+    <color name="legacy_control_normal">#99ffffff</color>
+    <color name="legacy_button_pressed">#fffea50b</color>
+    <color name="legacy_button_normal">#f3dbdbdb</color>
+
+    <color name="legacy_light_primary_dark">@color/legacy_primary_dark</color>
+    <color name="legacy_light_primary">@color/legacy_primary</color>
+    <color name="legacy_light_primary_light">@color/legacy_primary_light</color>
+    <color name="legacy_light_control_activated">@color/legacy_control_activated</color>
+    <color name="legacy_light_control_normal">#99000000</color>
+    <color name="legacy_light_button_pressed">@color/legacy_button_pressed</color>
+    <color name="legacy_light_button_normal">@color/legacy_button_normal</color>
+</resources>
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index f8f192f..7171450 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -14,6 +14,7 @@
      limitations under the License.
 -->
 
+<!-- Colors specific to Quantum themes. -->
 <resources>
     <color name="background_quantum_dark">@color/black</color>
     <color name="background_quantum_light">@color/white</color>
@@ -40,6 +41,7 @@
     <color name="highlighted_text_quantum_light">#660097a7</color>
 
     <!-- Primary & accent colors -->
+    <eat-comment />
 
     <color name="quantum_red_100">#fff4c7c3</color>
     <color name="quantum_red_300">#ffe67c73</color>
@@ -98,6 +100,7 @@
     <color name="quantum_deep_orange_A400">#ffff1744</color>
 
     <!-- Neutral colors -->
+    <eat-comment />
 
     <color name="quantum_grey_50">#fffafafa</color>
     <color name="quantum_grey_100">#fff5f5f5</color>
@@ -117,6 +120,7 @@
     <color name="quantum_brown_700">#ff5d4037</color>
 
     <!-- Text & foreground colors -->
+    <eat-comment />
 
     <color name="primary_text_default_quantum_light">#de000000</color>
     <color name="secondary_text_quantum_light">#8a000000</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 624ed73..f39155b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1212,6 +1212,9 @@
     <!-- 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 22c2b050..e88a6ee 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2168,6 +2168,7 @@
   <public type="attr" name="excludeId" />
   <public type="attr" name="excludeClass" />
   <public type="attr" name="hideOnContentScroll" />
+  <public type="attr" name="actionOverflowMenuStyle" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
@@ -2285,8 +2286,6 @@
   <public type="style" name="Widget.Quantum.Button.Inset" />
   <public type="style" name="Widget.Quantum.Button.Small" />
   <public type="style" name="Widget.Quantum.Button.Toggle" />
-  <public type="style" name="Widget.Quantum.Button.Paper" />
-  <public type="style" name="Widget.Quantum.Button.Paper.Color" />
   <public type="style" name="Widget.Quantum.ButtonBar" />
   <public type="style" name="Widget.Quantum.ButtonBar.AlertDialog" />
   <public type="style" name="Widget.Quantum.CalendarView" />
@@ -2309,6 +2308,7 @@
   <public type="style" name="Widget.Quantum.ListView.DropDown" />
   <public type="style" name="Widget.Quantum.MediaRouteButton" />
   <public type="style" name="Widget.Quantum.PopupMenu" />
+  <public type="style" name="Widget.Quantum.PopupMenu.Overflow" />
   <public type="style" name="Widget.Quantum.PopupWindow" />
   <public type="style" name="Widget.Quantum.ProgressBar" />
   <public type="style" name="Widget.Quantum.ProgressBar.Horizontal" />
@@ -2347,8 +2347,6 @@
   <public type="style" name="Widget.Quantum.Light.Button.Inset" />
   <public type="style" name="Widget.Quantum.Light.Button.Small" />
   <public type="style" name="Widget.Quantum.Light.Button.Toggle" />
-  <public type="style" name="Widget.Quantum.Light.Button.Paper" />
-  <public type="style" name="Widget.Quantum.Light.Button.Paper.Color" />
   <public type="style" name="Widget.Quantum.Light.ButtonBar" />
   <public type="style" name="Widget.Quantum.Light.ButtonBar.AlertDialog" />
   <public type="style" name="Widget.Quantum.Light.CalendarView" />
@@ -2370,6 +2368,7 @@
   <public type="style" name="Widget.Quantum.Light.ListView.DropDown" />
   <public type="style" name="Widget.Quantum.Light.MediaRouteButton" />
   <public type="style" name="Widget.Quantum.Light.PopupMenu" />
+  <public type="style" name="Widget.Quantum.Light.PopupMenu.Overflow" />
   <public type="style" name="Widget.Quantum.Light.PopupWindow" />
   <public type="style" name="Widget.Quantum.Light.ProgressBar" />
   <public type="style" name="Widget.Quantum.Light.ProgressBar.Horizontal" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 37716f7..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>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 23172c1..01c3017 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -372,16 +372,6 @@
         <item name="minWidth">48dip</item>
     </style>
 
-    <!-- Bordered paper button -->
-    <style name="Widget.Quantum.Button.Paper">
-        <!-- TODO: Specify pressed state animation. -->
-    </style>
-
-    <!-- Bordered paper button with color -->
-    <style name="Widget.Quantum.Button.Paper.Color">
-        <item name="background">@drawable/btn_color_quantum</item>
-    </style>
-
     <!-- Borderless ink button -->
     <style name="Widget.Quantum.Button.Borderless">
         <item name="background">@drawable/btn_borderless_quantum</item>
@@ -393,11 +383,6 @@
         <item name="minWidth">48dip</item>
     </style>
 
-    <!-- Borderless paper button -->
-    <style name="Widget.Quantum.Button.Borderless.Paper">
-        <!-- TODO: Specify pressed state animation. -->
-    </style>
-
     <style name="Widget.Quantum.Button.Inset">
         <item name="background">@drawable/button_inset</item>
     </style>
@@ -680,7 +665,8 @@
 
     <style name="Widget.Quantum.ListPopupWindow" parent="Widget.ListPopupWindow">
         <item name="dropDownSelector">@drawable/list_selector_quantum</item>
-        <item name="popupBackground">?attr/colorBackground</item>
+        <item name="popupBackground">@drawable/popup_background_quantum</item>
+        <item name="popupAnimationStyle">@style/Animation.Quantum.Popup</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
         <item name="dropDownWidth">wrap_content</item>
@@ -688,6 +674,10 @@
 
     <style name="Widget.Quantum.PopupMenu" parent="Widget.Quantum.ListPopupWindow"/>
 
+    <style name="Widget.Quantum.PopupMenu.Overflow">
+        <item name="overlapAnchor">true</item>
+    </style>
+
     <style name="Widget.Quantum.ActionButton" parent="Widget.ActionButton">
         <item name="minWidth">@dimen/action_button_min_width_quantum</item>
         <item name="minHeight">@dimen/action_button_min_height_quantum</item>
@@ -784,11 +774,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">
@@ -925,17 +912,9 @@
     <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowSmall" parent="Widget.Quantum.QuickContactBadgeSmall.WindowSmall"/>
     <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowMedium" parent="Widget.Quantum.QuickContactBadgeSmall.WindowMedium"/>
     <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowLarge" parent="Widget.Quantum.QuickContactBadgeSmall.WindowLarge"/>
-
-    <style name="Widget.Quantum.Light.ListPopupWindow" parent="Widget.ListPopupWindow">
-        <item name="dropDownSelector">@drawable/list_selector_quantum</item>
-        <item name="popupBackground">?attr/colorBackground</item>
-        <item name="dropDownVerticalOffset">0dip</item>
-        <item name="dropDownHorizontalOffset">0dip</item>
-        <item name="dropDownWidth">wrap_content</item>
-    </style>
-
-    <style name="Widget.Quantum.Light.PopupMenu" parent="Widget.Quantum.Light.ListPopupWindow"/>
-
+    <style name="Widget.Quantum.Light.ListPopupWindow" parent="Widget.Quantum.ListPopupWindow"/>
+    <style name="Widget.Quantum.Light.PopupMenu" parent="Widget.Quantum.ListPopupWindow"/>
+    <style name="Widget.Quantum.Light.PopupMenu.Overflow" parent="Widget.Quantum.PopupMenu.Overflow"/>
     <style name="Widget.Quantum.Light.ActionButton" parent="Widget.Quantum.ActionButton"/>
     <style name="Widget.Quantum.Light.ActionButton.Overflow" parent="Widget.Quantum.ActionButton.Overflow"/>
     <style name="Widget.Quantum.Light.Tab" parent="Widget.Quantum.Tab"/>
@@ -979,7 +958,16 @@
 
     <style name="Animation.Quantum" parent="Animation"/>
     <style name="Animation.Quantum.Activity" parent="Animation.Activity"/>
-    <style name="Animation.Quantum.Dialog" parent="Animation.Dialog"/>
+
+    <style name="Animation.Quantum.Dialog">
+        <item name="windowEnterAnimation">@anim/popup_enter_quantum</item>
+        <item name="windowExitAnimation">@anim/popup_exit_quantum</item>
+    </style>
+
+    <style name="Animation.Quantum.Popup">
+        <item name="windowEnterAnimation">@anim/popup_enter_quantum</item>
+        <item name="windowExitAnimation">@anim/popup_exit_quantum</item>
+    </style>
 
     <!-- Dialog styles -->
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 516a13b..a8a4b51 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1198,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" />
@@ -1269,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" />
@@ -1649,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" />
 
@@ -1861,9 +1864,5 @@
   <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..34ef508 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>
 
@@ -328,6 +336,7 @@
         <item name="actionDropDownStyle">@android:style/Widget.Spinner.DropDown</item>
         <item name="actionButtonStyle">@android:style/Widget.ActionButton</item>
         <item name="actionOverflowButtonStyle">@android:style/Widget.ActionButton.Overflow</item>
+        <item name="actionOverflowMenuStyle">?android:attr/popupMenuStyle</item>
         <item name="actionModeBackground">@android:drawable/cab_background_top_holo_dark</item>
         <item name="actionModeSplitBackground">@null</item>
         <item name="actionModeCloseDrawable">@android:drawable/ic_menu_close_clear_cancel</item>
@@ -437,6 +446,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 +806,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 +962,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>
@@ -1181,6 +1214,7 @@
         <item name="actionDropDownStyle">@android:style/Widget.Holo.Spinner.DropDown.ActionBar</item>
         <item name="actionButtonStyle">@android:style/Widget.Holo.ActionButton</item>
         <item name="actionOverflowButtonStyle">@android:style/Widget.Holo.ActionButton.Overflow</item>
+        <item name="actionOverflowMenuStyle">?android:attr/popupMenuStyle</item>
         <item name="actionModeBackground">@android:drawable/cab_background_top_holo_dark</item>
         <item name="actionModeSplitBackground">@android:drawable/cab_background_bottom_holo_dark</item>
         <item name="actionModeCloseDrawable">@android:drawable/ic_cab_done_holo_dark</item>
@@ -1268,6 +1302,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 80c10dd..dbc3d9e 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -299,6 +299,11 @@
          {@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>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index e3ac1ad..39c8beb 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -291,6 +291,7 @@
         <item name="actionDropDownStyle">@style/Widget.Quantum.Spinner.DropDown.ActionBar</item>
         <item name="actionButtonStyle">@style/Widget.Quantum.ActionButton</item>
         <item name="actionOverflowButtonStyle">@style/Widget.Quantum.ActionButton.Overflow</item>
+        <item name="actionOverflowMenuStyle">@android:style/Widget.Quantum.PopupMenu.Overflow</item>
         <item name="actionModeBackground">?attr/colorPrimaryDark</item>
         <item name="actionModeSplitBackground">?attr/colorPrimaryDark</item>
         <item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum</item>
@@ -636,6 +637,7 @@
         <item name="actionDropDownStyle">@style/Widget.Quantum.Light.Spinner.DropDown.ActionBar</item>
         <item name="actionButtonStyle">@style/Widget.Quantum.Light.ActionButton</item>
         <item name="actionOverflowButtonStyle">@style/Widget.Quantum.Light.ActionButton.Overflow</item>
+        <item name="actionOverflowMenuStyle">@android:style/Widget.Quantum.Light.PopupMenu.Overflow</item>
         <item name="actionModeBackground">@drawable/cab_background_top_holo_light</item>
         <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_light</item>
         <item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum</item>
@@ -717,9 +719,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 +855,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">
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/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java
new file mode 100644
index 0000000..0f3ea0e
--- /dev/null
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.bluetooth;
+
+import android.os.ParcelUuid;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test cases for {@link BluetoothUuid}.
+ * <p>
+ * To run this test, use adb shell am instrument -e class 'android.bluetooth.BluetoothUuidTest' -w
+ * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
+ */
+public class BluetoothUuidTest extends TestCase {
+
+    @SmallTest
+    public void testUuidParser() {
+        byte[] uuid16 = new byte[] {
+                0x0B, 0x11 };
+        assertEquals(ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"),
+                BluetoothUuid.parseUuidFrom(uuid16));
+
+        byte[] uuid32 = new byte[] {
+                0x0B, 0x11, 0x33, (byte) 0xFE };
+        assertEquals(ParcelUuid.fromString("FE33110B-0000-1000-8000-00805F9B34FB"),
+                BluetoothUuid.parseUuidFrom(uuid32));
+
+        byte[] uuid128 = new byte[] {
+                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+                0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, (byte) 0xFF };
+        assertEquals(ParcelUuid.fromString("FF0F0E0D-0C0B-0A09-0807-0060504030201"),
+                BluetoothUuid.parseUuidFrom(uuid128));
+    }
+}
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/src/android/os/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
index 6d33529..23b6780 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
@@ -73,7 +73,6 @@
                 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));
         }
@@ -116,36 +115,37 @@
                 imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
                         currentIme.mSubtypeName.toString()));
         assertEquals(imList.get(2), nextIme);
-        // "switchAwareLatinIme/fr" -> "nonSwitchAwareLatinIme/en_UK
+        // "switchAwareLatinIme/fr" -> "switchAwareJapaneseIme/ja_JP"
         currentIme = imList.get(2);
         nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
                 imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
                         currentIme.mSubtypeName.toString()));
-        assertEquals(imList.get(3), nextIme);
+        assertEquals(imList.get(5), nextIme);
+        // "switchAwareJapaneseIme/ja_JP" -> "switchAwareLatinIme/en_US"
+        currentIme = imList.get(5);
+        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" -> "switchAwareJapaneseIme/ja_JP"
+        // "nonSwitchAwareLatinIme/hi" -> "nonSwitchAwareJapaneseIme/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"
+        // "nonSwitchAwareJapaneseIme/ja_JP" -> "nonSwitchAwareLatinIme/en_UK"
         currentIme = imList.get(6);
         nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
                 imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
                         currentIme.mSubtypeName.toString()));
-        assertEquals(imList.get(0), nextIme);
+        assertEquals(imList.get(3), nextIme);
     }
 
     @SmallTest
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/guide/components/intents-common.jd b/docs/html/guide/components/intents-common.jd
index a0f7ce1..b4813a5 100644
--- a/docs/html/guide/components/intents-common.jd
+++ b/docs/html/guide/components/intents-common.jd
@@ -737,7 +737,7 @@
 <pre>
 public void editContact(Uri contactUri, String email) {
     Intent intent = new Intent(Intent.ACTION_EDIT);
-    intent.setDataAndType(contactUri, Contacts.CONTENT_TYPE);
+    intent.setData(contactUri);
     intent.putExtra(Intents.Insert.EMAIL, email);
     if (intent.resolveActivity(getPackageManager()) != null) {
         startActivity(intent);
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/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index d877502..3f8c45c 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -62,9 +62,8 @@
  * #updateTexImage} should not be called directly from the callback.
  */
 public class SurfaceTexture {
-
-    private EventHandler mEventHandler;
-    private OnFrameAvailableListener mOnFrameAvailableListener;
+    private final Looper mCreatorLooper;
+    private Handler mOnFrameAvailableHandler;
 
     /**
      * These fields are used by native code, do not access or modify.
@@ -83,7 +82,8 @@
     /**
      * Exception thrown when a SurfaceTexture couldn't be created or resized.
      *
-     * @deprecated No longer thrown. {@link Surface.OutOfResourcesException} is used instead.
+     * @deprecated No longer thrown. {@link android.view.Surface.OutOfResourcesException}
+     * is used instead.
      */
     @SuppressWarnings("serial")
     @Deprecated
@@ -100,10 +100,10 @@
      *
      * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
      *
-     * @throws OutOfResourcesException If the SurfaceTexture cannot be created.
+     * @throws Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
      */
     public SurfaceTexture(int texName) {
-        init(texName, false);
+        this(texName, false);
     }
 
     /**
@@ -121,20 +121,58 @@
      * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
      * @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
      *
-     * @throws throws OutOfResourcesException If the SurfaceTexture cannot be created.
+     * @throws Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
      */
     public SurfaceTexture(int texName, boolean singleBufferMode) {
-        init(texName, singleBufferMode);
+        mCreatorLooper = Looper.myLooper();
+        nativeInit(texName, singleBufferMode, new WeakReference<SurfaceTexture>(this));
     }
 
     /**
      * Register a callback to be invoked when a new image frame becomes available to the
-     * SurfaceTexture.  Note that this callback may be called on an arbitrary thread, so it is not
+     * SurfaceTexture.
+     * <p>
+     * This callback may be called on an arbitrary thread, so it is not
      * safe to call {@link #updateTexImage} without first binding the OpenGL ES context to the
      * thread invoking the callback.
+     * </p>
+     *
+     * @param listener The listener to set.
      */
-    public void setOnFrameAvailableListener(OnFrameAvailableListener l) {
-        mOnFrameAvailableListener = l;
+    public void setOnFrameAvailableListener(OnFrameAvailableListener listener) {
+        setOnFrameAvailableListener(listener, null);
+    }
+
+    /**
+     * Register a callback to be invoked when a new image frame becomes available to the
+     * SurfaceTexture.
+     * <p>
+     * If no handler is specified, then this callback may be called on an arbitrary thread,
+     * so it is not safe to call {@link #updateTexImage} without first binding the OpenGL ES
+     * context to the thread invoking the callback.
+     * </p>
+     *
+     * @param listener The listener to set.
+     * @param handler The handler on which the listener should be invoked, or null
+     * to use an arbitrary thread.
+     */
+    public void setOnFrameAvailableListener(final OnFrameAvailableListener listener,
+            Handler handler) {
+        if (listener != null) {
+            // Although we claim the thread is arbitrary, earlier implementation would
+            // prefer to send the callback on the creating looper or the main looper
+            // so we preserve this behavior here.
+            Looper looper = handler != null ? handler.getLooper() :
+                    mCreatorLooper != null ? mCreatorLooper : Looper.getMainLooper();
+            mOnFrameAvailableHandler = new Handler(looper, null, true /*async*/) {
+                @Override
+                public void handleMessage(Message msg) {
+                    listener.onFrameAvailable(SurfaceTexture.this);
+                }
+            };
+        } else {
+            mOnFrameAvailableHandler = null;
+        }
     }
 
     /**
@@ -285,49 +323,22 @@
         }
     }
 
-    private class EventHandler extends Handler {
-        public EventHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            if (mOnFrameAvailableListener != null) {
-                mOnFrameAvailableListener.onFrameAvailable(SurfaceTexture.this);
-            }
-        }
-    }
-
     /**
      * This method is invoked from native code only.
      */
     @SuppressWarnings({"UnusedDeclaration"})
-    private static void postEventFromNative(Object selfRef) {
-        WeakReference weakSelf = (WeakReference)selfRef;
-        SurfaceTexture st = (SurfaceTexture)weakSelf.get();
-        if (st == null) {
-            return;
-        }
-
-        if (st.mEventHandler != null) {
-            Message m = st.mEventHandler.obtainMessage();
-            st.mEventHandler.sendMessage(m);
+    private static void postEventFromNative(WeakReference<SurfaceTexture> weakSelf) {
+        SurfaceTexture st = weakSelf.get();
+        if (st != null) {
+            Handler handler = st.mOnFrameAvailableHandler;
+            if (handler != null) {
+                handler.sendEmptyMessage(0);
+            }
         }
     }
 
-    private void init(int texName, boolean singleBufferMode) throws Surface.OutOfResourcesException {
-        Looper looper;
-        if ((looper = Looper.myLooper()) != null) {
-            mEventHandler = new EventHandler(looper);
-        } else if ((looper = Looper.getMainLooper()) != null) {
-            mEventHandler = new EventHandler(looper);
-        } else {
-            mEventHandler = null;
-        }
-        nativeInit(texName, singleBufferMode, new WeakReference<SurfaceTexture>(this));
-    }
-
-    private native void nativeInit(int texName, boolean singleBufferMode, Object weakSelf)
+    private native void nativeInit(int texName, boolean singleBufferMode,
+            WeakReference<SurfaceTexture> weakSelf)
             throws Surface.OutOfResourcesException;
     private native void nativeFinalize();
     private native void nativeGetTransformMatrix(float[] mtx);
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 3446000..218a057 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -299,7 +299,7 @@
      */
     public void cancel() {
         if (mInner != null) {
-            mInner.end();
+            mInner.cancel();
         }
 
         if (mOuter != null) {
@@ -307,7 +307,7 @@
         }
 
         if (mAlpha != null) {
-            mAlpha.end();
+            mAlpha.cancel();
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 0992717..77712b6 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -182,28 +182,14 @@
 
     public VectorDrawable() {
         mVectorState = new VectorDrawableState(null);
-        mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 0);
-
-        setDuration(DEFAULT_DURATION);
     }
 
     private VectorDrawable(VectorDrawableState state, Resources res, Theme theme) {
         mVectorState = new VectorDrawableState(state);
-        mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 0);
 
         if (theme != null && canApplyTheme()) {
             applyTheme(theme);
         }
-
-        long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
-        if (duration == -1) {
-            // If duration is infinite, set to 1 hour.
-            // TODO: Define correct approach for infinite.
-            duration = DEFAULT_INFINITE_DURATION;
-            mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
-            mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
-        }
-        setDuration(duration);
     }
 
     @Override
@@ -212,118 +198,6 @@
     }
 
     @Override
-    public void jumpToCurrentState() {
-        stop();
-    }
-
-    /**
-     * Starts the animation.
-     */
-    public void start() {
-        mVectorState.mBasicAnimator.start();
-    }
-
-    /**
-     * Stops the animation and moves to the end state.
-     */
-    public void stop() {
-        mVectorState.mBasicAnimator.end();
-    }
-
-    /**
-     * Returns the current completion value for the animation.
-     *
-     * @return the current point on the animation, typically between 0 and 1
-     */
-    public float geAnimationFraction() {
-        return mVectorState.mVAnimatedPath.getValue();
-    }
-
-    /**
-     * Set the current completion value for the animation.
-     *
-     * @param value the point along the animation, typically between 0 and 1
-     */
-    public void setAnimationFraction(float value) {
-        mVectorState.mVAnimatedPath.setAnimationFraction(value);
-        invalidateSelf();
-    }
-
-    /**
-     * set the amount of time the animation will take
-     *
-     * @param duration amount of time in milliseconds
-     */
-    public void setDuration(long duration) {
-        mVectorState.mBasicAnimator.setDuration(duration);
-    }
-
-    /**
-     * Defines what this animation should do when it reaches the end. This
-     * setting is applied only when the repeat count is either greater than 0 or
-     * {@link ValueAnimator#INFINITE}.
-     *
-     * @param mode the animation mode, either {@link ValueAnimator#RESTART} or
-     *            {@link ValueAnimator#REVERSE}
-     */
-    public void setRepeatMode(int mode) {
-        mVectorState.mBasicAnimator.setRepeatMode(mode);
-    }
-
-    /**
-     * Sets animation to repeat
-     *
-     * @param repeat True if this drawable repeats its animation
-     */
-    public void setRepeatCount(int repeat) {
-        mVectorState.mBasicAnimator.setRepeatCount(repeat);
-    }
-
-    /**
-     * @return the animation repeat count, either a value greater than 0 or
-     *         {@link ValueAnimator#INFINITE}
-     */
-    public int getRepeatCount() {
-        return mVectorState.mBasicAnimator.getRepeatCount();
-    }
-
-    @Override
-    public boolean isStateful() {
-        return true;
-    }
-
-    @Override
-    protected boolean onStateChange(int[] state) {
-        super.onStateChange(state);
-
-        mVectorState.mVAnimatedPath.setState(state);
-
-        final int direction = mVectorState.mVAnimatedPath.getTrigger(state);
-        if (direction > 0) {
-            animateForward();
-        } else if (direction < 0) {
-            animateBackward();
-        }
-
-        invalidateSelf();
-        return true;
-    }
-
-    private void animateForward() {
-        if (!mVectorState.mBasicAnimator.isStarted()) {
-            mVectorState.mBasicAnimator.setFloatValues(0, 1);
-            start();
-        }
-    }
-
-    private void animateBackward() {
-        if (!mVectorState.mBasicAnimator.isStarted()) {
-            mVectorState.mBasicAnimator.setFloatValues(1, 0);
-            start();
-        }
-    }
-
-    @Override
     public void draw(Canvas canvas) {
         final int saveCount = canvas.save();
         final Rect bounds = getBounds();
@@ -432,7 +306,6 @@
 
             final VectorDrawable drawable = new VectorDrawable();
             drawable.inflate(resources, xpp, attrs);
-            drawable.setAnimationFraction(0);
 
             return drawable;
         } catch (XmlPullParserException e) {
@@ -536,35 +409,10 @@
 
     private void setAnimatedPath(VAnimatedPath animatedPath) {
         mVectorState.mVAnimatedPath = animatedPath;
-
-        long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
-        if (duration == -1) { // if it set to infinite set to 1 hour
-            duration = DEFAULT_INFINITE_DURATION; // TODO define correct
-                                                  // approach for infinite
-            mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
-            mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
-        }
-
-        setDuration(duration);
-        setAnimationFraction(0);
-    }
-
-    @Override
-    public boolean setVisible(boolean visible, boolean restart) {
-        boolean changed = super.setVisible(visible, restart);
-        if (visible) {
-            if (changed || restart) {
-                setAnimationFraction(0);
-            }
-        } else {
-            stop();
-        }
-        return changed;
     }
 
     private static class VectorDrawableState extends ConstantState {
         int mChangingConfigurations;
-        ValueAnimator mBasicAnimator;
         VAnimatedPath mVAnimatedPath;
         Rect mPadding;
 
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index d324439..eb0cac8 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -59,7 +59,8 @@
 		renderthread/DrawFrameTask.cpp \
 		renderthread/RenderProxy.cpp \
 		renderthread/RenderTask.cpp \
-		renderthread/RenderThread.cpp
+		renderthread/RenderThread.cpp \
+		renderthread/TimeLord.cpp
 
 	intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
 
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index ee16586..6a3003e 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -20,130 +20,13 @@
 
 #include <set>
 
+#include "RenderNode.h"
 #include "RenderProperties.h"
 
 namespace android {
 namespace uirenderer {
 
 /************************************************************
- *  Private header
- ************************************************************/
-
-typedef void (RenderProperties::*SetFloatProperty)(float value);
-typedef float (RenderProperties::*GetFloatProperty)() const;
-
-struct PropertyAccessors {
-    GetFloatProperty getter;
-    SetFloatProperty setter;
-};
-
-// Maps RenderProperty enum to accessors
-static const PropertyAccessors PROPERTY_ACCESSOR_LUT[] = {
-    {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
-    {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
-    {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
-    {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
-    {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
-    {&RenderProperties::getRotation, &RenderProperties::setRotation },
-    {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
-    {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
-    {&RenderProperties::getX, &RenderProperties::setX },
-    {&RenderProperties::getY, &RenderProperties::setY },
-    {&RenderProperties::getZ, &RenderProperties::setZ },
-    {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
-};
-
-// Helper class to contain generic animator helpers
-class BaseAnimator {
-public:
-    BaseAnimator();
-    virtual ~BaseAnimator();
-
-    void setInterpolator(Interpolator* interpolator);
-    void setDuration(nsecs_t durationInMs);
-
-    bool isFinished() { return mPlayState == FINISHED; }
-
-protected:
-    // This is the main animation entrypoint that subclasses should call
-    // to generate the onAnimation* lifecycle events
-    // Returns true if the animation has finished, false otherwise
-    bool animateFrame(nsecs_t frameTime);
-
-    // Called when PlayState switches from PENDING to RUNNING
-    virtual void onAnimationStarted() {}
-    virtual void onAnimationUpdated(float fraction) = 0;
-    virtual void onAnimationFinished() {}
-
-private:
-    enum PlayState {
-        PENDING,
-        RUNNING,
-        FINISHED,
-    };
-
-    Interpolator* mInterpolator;
-    PlayState mPlayState;
-    long mStartTime;
-    long mDuration;
-};
-
-// Hide the base classes & private bits from the exported RenderPropertyAnimator
-// in this Impl class so that subclasses of RenderPropertyAnimator don't require
-// knowledge of the inner guts but only the public virtual methods.
-// Animates a single property
-class RenderPropertyAnimatorImpl : public BaseAnimator {
-public:
-    RenderPropertyAnimatorImpl(GetFloatProperty getter, SetFloatProperty setter,
-            RenderPropertyAnimator::DeltaValueType deltaType, float delta);
-    ~RenderPropertyAnimatorImpl();
-
-    bool animate(RenderProperties* target, TreeInfo& info);
-
-protected:
-    virtual void onAnimationStarted();
-    virtual void onAnimationUpdated(float fraction);
-
-private:
-    // mTarget is only valid inside animate()
-    RenderProperties* mTarget;
-    GetFloatProperty mGetter;
-    SetFloatProperty mSetter;
-
-    RenderPropertyAnimator::DeltaValueType mDeltaValueType;
-    float mDeltaValue;
-    float mFromValue;
-};
-
-RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
-        DeltaValueType deltaType, float deltaValue) {
-    PropertyAccessors pa = PROPERTY_ACCESSOR_LUT[property];
-    mImpl = new RenderPropertyAnimatorImpl(pa.getter, pa.setter, deltaType, deltaValue);
-}
-
-RenderPropertyAnimator::~RenderPropertyAnimator() {
-    delete mImpl;
-    mImpl = NULL;
-}
-
-void RenderPropertyAnimator::setInterpolator(Interpolator* interpolator) {
-    mImpl->setInterpolator(interpolator);
-}
-
-void RenderPropertyAnimator::setDuration(nsecs_t durationInMs) {
-    mImpl->setDuration(durationInMs);
-}
-
-bool RenderPropertyAnimator::isFinished() {
-    return mImpl->isFinished();
-}
-
-bool RenderPropertyAnimator::animate(RenderProperties* target, TreeInfo& info) {
-    return mImpl->animate(target, info);
-}
-
-
-/************************************************************
  *  Base animator
  ************************************************************/
 
@@ -168,10 +51,10 @@
     mDuration = duration;
 }
 
-bool BaseAnimator::animateFrame(nsecs_t frameTime) {
+bool BaseAnimator::animateFrame(TreeInfo& info) {
     if (mPlayState == PENDING) {
         mPlayState = RUNNING;
-        mStartTime = frameTime;
+        mStartTime = info.frameTimeMs;
         // No interpolator was set, use the default
         if (!mInterpolator) {
             setInterpolator(Interpolator::createDefaultInterpolator());
@@ -181,7 +64,7 @@
 
     float fraction = 1.0f;
     if (mPlayState == RUNNING) {
-        fraction = mDuration > 0 ? (float)(frameTime - mStartTime) / mDuration : 1.0f;
+        fraction = mDuration > 0 ? (float)(info.frameTimeMs - mStartTime) / mDuration : 1.0f;
         if (fraction >= 1.0f) {
             fraction = 1.0f;
             mPlayState = FINISHED;
@@ -192,48 +75,140 @@
 
     if (mPlayState == FINISHED) {
         onAnimationFinished();
+        callOnFinishedListener(info);
         return true;
     }
     return false;
 }
 
+void BaseAnimator::callOnFinishedListener(TreeInfo& info) {
+    if (mListener.get()) {
+        if (!info.animationHook) {
+            mListener->onAnimationFinished(this);
+        } else {
+            info.animationHook->callOnFinished(this, mListener.get());
+        }
+    }
+}
+
+/************************************************************
+ *  BaseRenderNodeAnimator
+ ************************************************************/
+
+BaseRenderNodeAnimator::BaseRenderNodeAnimator(
+                BaseRenderNodeAnimator::DeltaValueType deltaType, float delta)
+        : mTarget(0)
+        , mDeltaValueType(deltaType)
+        , mDeltaValue(delta)
+        , mFromValue(-1) {
+}
+
+bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
+    mTarget = target;
+    bool finished = animateFrame(info);
+    mTarget = NULL;
+    return finished;
+}
+
+void BaseRenderNodeAnimator::onAnimationStarted() {
+    mFromValue = getValue();
+
+    if (mDeltaValueType == BaseRenderNodeAnimator::ABSOLUTE) {
+        mDeltaValue = (mDeltaValue - mFromValue);
+        mDeltaValueType = BaseRenderNodeAnimator::DELTA;
+    }
+}
+
+void BaseRenderNodeAnimator::onAnimationUpdated(float fraction) {
+    float value = mFromValue + (mDeltaValue * fraction);
+    setValue(value);
+}
+
 /************************************************************
  *  RenderPropertyAnimator
  ************************************************************/
 
-RenderPropertyAnimatorImpl::RenderPropertyAnimatorImpl(
-                GetFloatProperty getter, SetFloatProperty setter,
-                RenderPropertyAnimator::DeltaValueType deltaType, float delta)
-        : mTarget(0)
-        , mGetter(getter)
-        , mSetter(setter)
-        , mDeltaValueType(deltaType)
-        , mDeltaValue(delta)
-        , mFromValue(-1) {
+// Maps RenderProperty enum to accessors
+const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
+    {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
+    {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
+    {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
+    {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
+    {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
+    {&RenderProperties::getRotation, &RenderProperties::setRotation },
+    {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
+    {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
+    {&RenderProperties::getX, &RenderProperties::setX },
+    {&RenderProperties::getY, &RenderProperties::setY },
+    {&RenderProperties::getZ, &RenderProperties::setZ },
+    {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
+};
+
+RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
+                DeltaValueType deltaType, float deltaValue)
+        : BaseRenderNodeAnimator(deltaType, deltaValue)
+        , mPropertyAccess(PROPERTY_ACCESSOR_LUT[property]) {
 }
 
-RenderPropertyAnimatorImpl::~RenderPropertyAnimatorImpl() {
+float RenderPropertyAnimator::getValue() const {
+    return (target()->animatorProperties().*mPropertyAccess.getter)();
 }
 
-bool RenderPropertyAnimatorImpl::animate(RenderProperties* target, TreeInfo& info) {
-    mTarget = target;
-    bool finished = animateFrame(info.frameTimeMs);
-    mTarget = NULL;
-    return finished;
+void RenderPropertyAnimator::setValue(float value) {
+    (target()->animatorProperties().*mPropertyAccess.setter)(value);
 }
 
-void RenderPropertyAnimatorImpl::onAnimationStarted() {
-    mFromValue = (mTarget->*mGetter)();
+/************************************************************
+ *  CanvasPropertyPrimitiveAnimator
+ ************************************************************/
 
-    if (mDeltaValueType == RenderPropertyAnimator::ABSOLUTE) {
-        mDeltaValue = (mDeltaValue - mFromValue);
-        mDeltaValueType = RenderPropertyAnimator::DELTA;
+CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
+                CanvasPropertyPrimitive* property, DeltaValueType deltaType, float deltaValue)
+        : BaseRenderNodeAnimator(deltaType, deltaValue)
+        , mProperty(property) {
+}
+
+float CanvasPropertyPrimitiveAnimator::getValue() const {
+    return mProperty->value;
+}
+
+void CanvasPropertyPrimitiveAnimator::setValue(float value) {
+    mProperty->value = value;
+}
+
+/************************************************************
+ *  CanvasPropertySkPaintAnimator
+ ************************************************************/
+
+CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
+                CanvasPropertyPaint* property, PaintField field,
+                DeltaValueType deltaType, float deltaValue)
+        : BaseRenderNodeAnimator(deltaType, deltaValue)
+        , mProperty(property)
+        , mField(field) {
+}
+
+float CanvasPropertyPaintAnimator::getValue() const {
+    switch (mField) {
+    case STROKE_WIDTH:
+        return mProperty->value.getStrokeWidth();
+    case ALPHA:
+        return mProperty->value.getAlpha();
     }
+    LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
+    return -1;
 }
 
-void RenderPropertyAnimatorImpl::onAnimationUpdated(float fraction) {
-    float value = mFromValue + (mDeltaValue * fraction);
-    (mTarget->*mSetter)(value);
+void CanvasPropertyPaintAnimator::setValue(float value) {
+    switch (mField) {
+    case STROKE_WIDTH:
+        mProperty->value.setStrokeWidth(value);
+        return;
+    case ALPHA:
+        mProperty->value.setAlpha(value);
+        return;
+    }
+    LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
 }
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 1c8361b..0b074cc 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -17,18 +17,72 @@
 #define ANIMATOR_H
 
 #include <cutils/compiler.h>
+#include <utils/StrongPointer.h>
 
+#include "CanvasProperty.h"
 #include "Interpolator.h"
 #include "TreeInfo.h"
+#include "utils/Macros.h"
 #include "utils/VirtualLightRefBase.h"
 
 namespace android {
 namespace uirenderer {
 
+class RenderNode;
 class RenderProperties;
-class RenderPropertyAnimatorImpl;
 
-class RenderPropertyAnimator : public VirtualLightRefBase {
+class AnimationListener : public VirtualLightRefBase {
+public:
+    ANDROID_API virtual void onAnimationFinished(BaseAnimator*) = 0;
+protected:
+    ANDROID_API virtual ~AnimationListener() {}
+};
+
+// Helper class to contain generic animator helpers
+class BaseAnimator : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(BaseAnimator);
+public:
+
+    ANDROID_API void setInterpolator(Interpolator* interpolator);
+    ANDROID_API void setDuration(nsecs_t durationInMs);
+    ANDROID_API void setListener(AnimationListener* listener) {
+        mListener = listener;
+    }
+
+    bool isFinished() { return mPlayState == FINISHED; }
+
+protected:
+    BaseAnimator();
+    virtual ~BaseAnimator();
+
+    // This is the main animation entrypoint that subclasses should call
+    // to generate the onAnimation* lifecycle events
+    // Returns true if the animation has finished, false otherwise
+    bool animateFrame(TreeInfo& info);
+
+    // Called when PlayState switches from PENDING to RUNNING
+    virtual void onAnimationStarted() {}
+    virtual void onAnimationUpdated(float fraction) = 0;
+    virtual void onAnimationFinished() {}
+
+private:
+    void callOnFinishedListener(TreeInfo& info);
+
+    enum PlayState {
+        PENDING,
+        RUNNING,
+        FINISHED,
+    };
+
+    Interpolator* mInterpolator;
+    PlayState mPlayState;
+    long mStartTime;
+    long mDuration;
+
+   sp<AnimationListener> mListener;
+};
+
+class BaseRenderNodeAnimator : public BaseAnimator {
 public:
     // Since the UI thread doesn't necessarily know what the current values
     // actually are and thus can't do the calculations, this is used to inform
@@ -43,6 +97,29 @@
         DELTA,
     };
 
+    bool animate(RenderNode* target, TreeInfo& info);
+
+protected:
+    BaseRenderNodeAnimator(DeltaValueType deltaType, float deltaValue);
+
+    RenderNode* target() const { return mTarget; }
+    virtual float getValue() const = 0;
+    virtual void setValue(float value) = 0;
+
+private:
+    virtual void onAnimationStarted();
+    virtual void onAnimationUpdated(float fraction);
+
+    // mTarget is only valid inside animate()
+    RenderNode* mTarget;
+
+    BaseRenderNodeAnimator::DeltaValueType mDeltaValueType;
+    float mDeltaValue;
+    float mFromValue;
+};
+
+class RenderPropertyAnimator : public BaseRenderNodeAnimator {
+public:
     enum RenderProperty {
         TRANSLATION_X = 0,
         TRANSLATION_Y,
@@ -58,19 +135,53 @@
         ALPHA,
     };
 
-    ANDROID_API void setInterpolator(Interpolator* interpolator);
-    ANDROID_API void setDuration(nsecs_t durationInMs);
-    ANDROID_API bool isFinished();
-
-    bool animate(RenderProperties* target, TreeInfo& info);
+    ANDROID_API RenderPropertyAnimator(RenderProperty property,
+                DeltaValueType deltaType, float deltaValue);
 
 protected:
-    ANDROID_API RenderPropertyAnimator(RenderProperty property, DeltaValueType deltaType,
-            float deltaValue);
-    ANDROID_API virtual ~RenderPropertyAnimator();
+    ANDROID_API virtual float getValue() const;
+    ANDROID_API virtual void setValue(float value);
 
 private:
-    RenderPropertyAnimatorImpl* mImpl;
+    typedef void (RenderProperties::*SetFloatProperty)(float value);
+    typedef float (RenderProperties::*GetFloatProperty)() const;
+
+    struct PropertyAccessors {
+        GetFloatProperty getter;
+        SetFloatProperty setter;
+    };
+
+    PropertyAccessors mPropertyAccess;
+
+    static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
+};
+
+class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
+public:
+    ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
+            DeltaValueType deltaType, float deltaValue);
+protected:
+    ANDROID_API virtual float getValue() const;
+    ANDROID_API virtual void setValue(float value);
+private:
+    sp<CanvasPropertyPrimitive> mProperty;
+};
+
+class CanvasPropertyPaintAnimator : public BaseRenderNodeAnimator {
+public:
+    enum PaintField {
+        STROKE_WIDTH = 0,
+        ALPHA,
+    };
+
+    ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
+            PaintField field, DeltaValueType deltaType, float deltaValue);
+protected:
+    ANDROID_API virtual float getValue() const;
+    ANDROID_API virtual void setValue(float value);
+private:
+    sp<CanvasPropertyPaint> mProperty;
+    PaintField mField;
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/CanvasProperty.h b/libs/hwui/CanvasProperty.h
new file mode 100644
index 0000000..2e1d176
--- /dev/null
+++ b/libs/hwui/CanvasProperty.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef CANVASPROPERTY_H
+#define CANVASPROPERTY_H
+
+#include "utils/Macros.h"
+#include "utils/VirtualLightRefBase.h"
+
+#include <SkPaint.h>
+
+namespace android {
+namespace uirenderer {
+
+class CanvasPropertyPrimitive : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(CanvasPropertyPrimitive);
+public:
+    CanvasPropertyPrimitive(float initialValue) : value(initialValue) {}
+
+    float value;
+};
+
+class CanvasPropertyPaint : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(CanvasPropertyPaint);
+public:
+    CanvasPropertyPaint(const SkPaint& initialValue) : value(initialValue) {}
+
+    SkPaint value;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* CANVASPROPERTY_H */
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index fe70d13..eaeb772 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -140,6 +140,14 @@
     void addChild(DrawDisplayListOp* childOp);
     const Vector<DrawDisplayListOp*>& children() { return mChildren; }
 
+    void refProperty(CanvasPropertyPrimitive* prop) {
+        mReferenceHolders.push(prop);
+    }
+
+    void refProperty(CanvasPropertyPaint* prop) {
+        mReferenceHolders.push(prop);
+    }
+
 private:
     Vector< sp<VirtualLightRefBase> > mReferenceHolders;
 
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 6dfb918..ce92beb 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1198,6 +1198,27 @@
     float mRadius;
 };
 
+class DrawCirclePropsOp : public DrawOp {
+public:
+    DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
+            : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
+
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
+        return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
+    }
+
+    virtual void output(int level, uint32_t logFlags) const {
+        OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
+    }
+
+    virtual const char* name() { return "DrawCircleProps"; }
+
+private:
+    float* mX;
+    float* mY;
+    float* mRadius;
+};
+
 class DrawOvalOp : public DrawStrokableOp {
 public:
     DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index e36d975..8afd106 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -299,6 +299,17 @@
     return DrawGlInfo::kStatusDone;
 }
 
+status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+        CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+    mDisplayListData->refProperty(x);
+    mDisplayListData->refProperty(y);
+    mDisplayListData->refProperty(radius);
+    mDisplayListData->refProperty(paint);
+    addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
+            &radius->value, &paint->value));
+    return DrawGlInfo::kStatusDone;
+}
+
 status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
         const SkPaint* paint) {
     paint = refPaint(paint);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 04c5a73..25e78c1 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -135,6 +135,8 @@
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint* paint);
     virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+    virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+                CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
     virtual status_t drawOval(float left, float top, float right, float bottom,
             const SkPaint* paint);
     virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index b52003c..647c281 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -737,30 +737,34 @@
             // a null path is OK because there are no custom kernels used
             // hence nothing gets cached by RS
             if (!mRs->init("", RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) {
+                mRs.clear();
                 ALOGE("blur RS failed to init");
+            } else {
+                mRsElement = RSC::Element::A_8(mRs);
+                mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement);
             }
-
-            mRsElement = RSC::Element::A_8(mRs);
-            mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement);
         }
+        if (mRs != 0) {
+            RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0);
+            RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t,
+                    RS_ALLOCATION_MIPMAP_NONE,
+                    RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
+                    *image);
+            RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t,
+                    RS_ALLOCATION_MIPMAP_NONE,
+                    RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
+                    outImage);
 
-        RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0);
-        RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t,
-                RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
-                *image);
-        RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t,
-                RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
-                outImage);
+            mRsScript->setRadius(radius);
+            mRsScript->setInput(ain);
+            mRsScript->forEach(aout);
 
-        mRsScript->setRadius(radius);
-        mRsScript->setInput(ain);
-        mRsScript->forEach(aout);
+            // replace the original image's pointer, avoiding a copy back to the original buffer
+            free(*image);
+            *image = outImage;
 
-        // replace the original image's pointer, avoiding a copy back to the original buffer
-        free(*image);
-        *image = outImage;
-
-        return;
+            return;
+        }
     }
 #endif
 
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b49d1e1..7794abc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -49,6 +49,7 @@
 #include "UvMapper.h"
 #include "Vertex.h"
 #include "Caches.h"
+#include "CanvasProperty.h"
 
 namespace android {
 namespace uirenderer {
@@ -200,6 +201,12 @@
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint* paint);
     virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+    virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+            CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+        // TODO: Remove once android_view_GLES20Canvas uses DisplayListRenderer
+        // directly
+        return drawCircle(x->value, y->value, radius->value, &paint->value);
+    }
     virtual status_t drawOval(float left, float top, float right, float bottom,
             const SkPaint* paint);
     virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 7a9c181..9902ff1 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -109,7 +109,7 @@
     prepareSubTree(info, mDisplayListData);
 }
 
-static bool is_finished(const sp<RenderPropertyAnimator>& animator) {
+static bool is_finished(const sp<BaseRenderNodeAnimator>& animator) {
     return animator->isFinished();
 }
 
@@ -120,7 +120,7 @@
     }
     if (mNeedsAnimatorsSync) {
         mAnimators.resize(mStagingAnimators.size());
-        std::vector< sp<RenderPropertyAnimator> >::iterator it;
+        std::vector< sp<BaseRenderNodeAnimator> >::iterator it;
         // hint: this means copy_if_not()
         it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
                 mAnimators.begin(), is_finished);
@@ -141,36 +141,32 @@
 
 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();
-    info.hasAnimations |= mAnimators.size();
+    info.out.hasAnimations |= mAnimators.size();
 }
 
 void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
     if (subtree) {
         TextureCache& cache = Caches::getInstance().textureCache;
-        info.hasFunctors |= subtree->functorCount;
+        info.out.hasFunctors |= subtree->functorCount;
         // TODO: Fix ownedBitmapResources to not require disabling prepareTextures
         // and thus falling out of async drawing path.
         if (subtree->ownedBitmapResources.size()) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 294f436..159903c 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -128,6 +128,10 @@
         return mProperties;
     }
 
+    RenderProperties& animatorProperties() {
+        return mProperties;
+    }
+
     const RenderProperties& stagingProperties() {
         return mStagingProperties;
     }
@@ -148,13 +152,13 @@
     ANDROID_API virtual void prepareTree(TreeInfo& info);
 
     // UI thread only!
-    ANDROID_API void addAnimator(const sp<RenderPropertyAnimator>& animator) {
+    ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
         mStagingAnimators.insert(animator);
         mNeedsAnimatorsSync = true;
     }
 
     // UI thread only!
-    ANDROID_API void removeAnimator(const sp<RenderPropertyAnimator>& animator) {
+    ANDROID_API void removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
         mStagingAnimators.erase(animator);
         mNeedsAnimatorsSync = true;
     }
@@ -233,8 +237,8 @@
     DisplayListData* mStagingDisplayListData;
 
     bool mNeedsAnimatorsSync;
-    std::set< sp<RenderPropertyAnimator> > mStagingAnimators;
-    std::vector< sp<RenderPropertyAnimator> > mAnimators;
+    std::set< sp<BaseRenderNodeAnimator> > mStagingAnimators;
+    std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
 
     /**
      * Draw time state - these properties are only set and used during rendering
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 8957607..fc5994c 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -16,44 +16,51 @@
 #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 {
     // The defaults here should be safe for everyone but DrawFrameTask to use as-is.
     TreeInfo()
-            : hasFunctors(false)
-            , prepareTextures(false)
-            , performStagingPush(true)
-            , frameTimeMs(0)
-            , evaluateAnimations(false)
-            , hasAnimations(false)
-            , animationListener(0)
+        : frameTimeMs(0)
+        , animationHook(NULL)
+        , prepareTextures(false)
+        , performStagingPush(true)
+        , evaluateAnimations(false)
     {}
 
-    bool hasFunctors;
+    nsecs_t frameTimeMs;
+    AnimationHook* animationHook;
     bool prepareTextures;
     bool performStagingPush;
-
-    // Animations
-    nsecs_t frameTimeMs;
     bool evaluateAnimations;
-    // This is only updated if evaluateAnimations is true
-    bool hasAnimations;
-    AnimationListener* animationListener;
+
+    struct Out {
+        Out()
+            : hasFunctors(false)
+            , hasAnimations(false)
+            , requiresUiRedraw(false)
+        {}
+        bool hasFunctors;
+        // This is only updated if evaluateAnimations is true
+        bool hasAnimations;
+        // This is set to true if there is an animation that RenderThread cannot
+        // animate itself, such as if hasFunctors is true
+        // This is only set if hasAnimations is true
+        bool requiresUiRedraw;
+    } out;
 
     // TODO: Damage calculations
 };
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 63f4b95..fc3548c 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -391,10 +391,20 @@
     mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface);
 }
 
+void CanvasContext::prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters,
+        TreeInfo& info) {
+    LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot prepareDraw without a canvas!");
+    makeCurrent();
+
+    processLayerUpdates(layerUpdaters, info);
+    if (info.out.hasAnimations) {
+        // TODO: Uh... crap?
+    }
+    prepareTree(info);
+}
+
 void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
         TreeInfo& info) {
-    LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
-    makeCurrent();
     for (size_t i = 0; i < layerUpdaters->size(); i++) {
         DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
         bool success = update->apply(info);
@@ -406,11 +416,19 @@
 }
 
 void CanvasContext::prepareTree(TreeInfo& info) {
+    mRenderThread.removeFrameCallback(this);
+
+    info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
     mRootRenderNode->prepareTree(info);
 
-    if (info.hasAnimations && !info.hasFunctors) {
-        // TODO: Functors
-        mRenderThread.postFrameCallback(this);
+    if (info.out.hasAnimations) {
+        if (info.out.hasFunctors) {
+            info.out.requiresUiRedraw = true;
+        } else if (!info.out.requiresUiRedraw) {
+            // If animationsNeedsRedraw is set don't bother posting for an RT anim
+            // as we will just end up fighting the UI thread.
+            mRenderThread.postFrameCallback(this);
+        }
     }
 }
 
@@ -449,12 +467,11 @@
 }
 
 // Called by choreographer to do an RT-driven animation
-void CanvasContext::doFrame(nsecs_t frameTimeNanos) {
+void CanvasContext::doFrame() {
     ATRACE_CALL();
 
     TreeInfo info;
     info.evaluateAnimations = true;
-    info.frameTimeMs = nanoseconds_to_milliseconds(frameTimeNanos);
     info.performStagingPush = false;
     info.prepareTextures = false;
 
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0873ad4..a95e27a 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -53,13 +53,12 @@
     void pauseSurface(EGLNativeWindowType window);
     void setup(int width, int height);
     void makeCurrent();
-    void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
-    void prepareTree(TreeInfo& info);
+    void prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
     void draw(Rect* dirty);
     void destroyCanvasAndSurface();
 
     // IFrameCallback, Chroreographer-driven frame callback entry point
-    virtual void doFrame(nsecs_t frameTimeNanos);
+    virtual void doFrame();
 
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
 
@@ -71,6 +70,9 @@
     Layer* createTextureLayer();
 
 private:
+    void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
+    void prepareTree(TreeInfo& info);
+
     void setSurface(EGLNativeWindowType window);
     void swapBuffers();
     void requireSurface();
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index ff4be71..3b8786c 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -30,13 +30,18 @@
 namespace uirenderer {
 namespace renderthread {
 
-DrawFrameTask::DrawFrameTask() : mContext(0) {
+DrawFrameTask::DrawFrameTask()
+        : mRenderThread(NULL)
+        , mContext(NULL)
+        , mFrameTimeNanos(0)
+        , mSyncResult(kSync_OK) {
 }
 
 DrawFrameTask::~DrawFrameTask() {
 }
 
-void DrawFrameTask::setContext(CanvasContext* context) {
+void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context) {
+    mRenderThread = thread;
     mContext = context;
 }
 
@@ -59,18 +64,23 @@
     mDirty.set(left, top, right, bottom);
 }
 
-void DrawFrameTask::drawFrame(RenderThread* renderThread) {
+int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos) {
     LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
 
-    postAndWait(renderThread);
+    mSyncResult = kSync_OK;
+    mFrameTimeNanos = frameTimeNanos;
+    postAndWait();
 
     // Reset the single-frame data
+    mFrameTimeNanos = 0;
     mDirty.setEmpty();
+
+    return mSyncResult;
 }
 
-void DrawFrameTask::postAndWait(RenderThread* renderThread) {
+void DrawFrameTask::postAndWait() {
     AutoMutex _lock(mLock);
-    renderThread->queue(this);
+    mRenderThread->queue(this);
     mSignal.wait(mLock);
 }
 
@@ -99,21 +109,25 @@
     info.prepareTextures = true;
     info.performStagingPush = true;
     info.evaluateAnimations = true;
-    // TODO: Get this from Choreographer
-    nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
-    info.frameTimeMs = nanoseconds_to_milliseconds(frameTimeNs);
 }
 
 bool DrawFrameTask::syncFrameState() {
     ATRACE_CALL();
+    mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos);
     mContext->makeCurrent();
     Caches::getInstance().textureCache.resetMarkInUse();
     TreeInfo info;
     initTreeInfo(info);
-    mContext->processLayerUpdates(&mLayers, info);
-    mContext->prepareTree(info);
+    mContext->prepareDraw(&mLayers, info);
+    if (info.out.hasAnimations) {
+        // TODO: dirty calculations, for now just do a full-screen inval
+        mDirty.setEmpty();
+        if (info.out.requiresUiRedraw) {
+            mSyncResult |= kSync_UIRedrawRequired;
+        }
+    }
     // If prepareTextures is false, we ran out of texture cache space
-    return !info.hasFunctors && info.prepareTextures;
+    return !info.out.hasFunctors && info.prepareTextures;
 }
 
 void DrawFrameTask::unblockUiThread() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index c280868..b9307e1 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -37,6 +37,11 @@
 class CanvasContext;
 class RenderThread;
 
+enum SyncResult {
+    kSync_OK = 0,
+    kSync_UIRedrawRequired = 1 << 1,
+};
+
 /*
  * This is a special Super Task. It is re-used multiple times by RenderProxy,
  * and contains state (such as layer updaters & new DisplayListDatas) that is
@@ -48,30 +53,34 @@
     DrawFrameTask();
     virtual ~DrawFrameTask();
 
-    void setContext(CanvasContext* context);
+    void setContext(RenderThread* thread, CanvasContext* context);
 
     void addLayer(DeferredLayerUpdater* layer);
     void removeLayer(DeferredLayerUpdater* layer);
 
     void setDirty(int left, int top, int right, int bottom);
-    void drawFrame(RenderThread* renderThread);
+    int drawFrame(nsecs_t frameTimeNanos);
 
     virtual void run();
 
 private:
-    void postAndWait(RenderThread* renderThread);
+    void postAndWait();
     bool syncFrameState();
     void unblockUiThread();
 
     Mutex mLock;
     Condition mSignal;
 
+    RenderThread* mRenderThread;
     CanvasContext* mContext;
 
     /*********************************************
      *  Single frame data
      *********************************************/
     Rect mDirty;
+    nsecs_t mFrameTimeNanos;
+
+    int mSyncResult;
 
     /*********************************************
      *  Multi frame data
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 87886e6..c2806fa 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -62,7 +62,7 @@
     args->translucent = translucent;
     args->rootRenderNode = rootRenderNode;
     mContext = (CanvasContext*) postAndWait(task);
-    mDrawFrameTask.setContext(mContext);
+    mDrawFrameTask.setContext(&mRenderThread, mContext);
 }
 
 RenderProxy::~RenderProxy() {
@@ -79,13 +79,38 @@
         SETUP_TASK(destroyContext);
         args->context = mContext;
         mContext = 0;
-        mDrawFrameTask.setContext(0);
+        mDrawFrameTask.setContext(NULL, NULL);
         // This is also a fence as we need to be certain that there are no
         // outstanding mDrawFrame tasks posted before it is destroyed
         postAndWait(task);
     }
 }
 
+CREATE_BRIDGE2(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) {
+    args->thread->timeLord().setFrameInterval(args->frameIntervalNanos);
+    return NULL;
+}
+
+void RenderProxy::setFrameInterval(nsecs_t frameIntervalNanos) {
+    SETUP_TASK(setFrameInterval);
+    args->thread = &mRenderThread;
+    args->frameIntervalNanos = frameIntervalNanos;
+    post(task);
+}
+
+CREATE_BRIDGE0(loadSystemProperties) {
+    bool needsRedraw = false;
+    if (Caches::hasInstance()) {
+        needsRedraw = Caches::getInstance().initProperties();
+    }
+    return (void*) needsRedraw;
+}
+
+bool RenderProxy::loadSystemProperties() {
+    SETUP_TASK(loadSystemProperties);
+    return (bool) postAndWait(task);
+}
+
 CREATE_BRIDGE2(initialize, CanvasContext* context, EGLNativeWindowType window) {
     return (void*) args->context->initialize(args->window);
 }
@@ -134,10 +159,10 @@
     post(task);
 }
 
-void RenderProxy::syncAndDrawFrame(
+int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos,
         int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
     mDrawFrameTask.setDirty(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
-    mDrawFrameTask.drawFrame(&mRenderThread);
+    return mDrawFrameTask.drawFrame(frameTimeNanos);
 }
 
 CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index eab1395..013c3bd 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -25,6 +25,7 @@
 #include <utils/Condition.h>
 #include <utils/Functor.h>
 #include <utils/Mutex.h>
+#include <utils/Timers.h>
 #include <utils/StrongPointer.h>
 #include <utils/Vector.h>
 
@@ -59,11 +60,14 @@
     ANDROID_API RenderProxy(bool translucent, RenderNode* rootNode);
     ANDROID_API virtual ~RenderProxy();
 
+    ANDROID_API void setFrameInterval(nsecs_t frameIntervalNanos);
+    ANDROID_API bool loadSystemProperties();
+
     ANDROID_API bool initialize(const sp<ANativeWindow>& window);
     ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
     ANDROID_API void pauseSurface(const sp<ANativeWindow>& window);
     ANDROID_API void setup(int width, int height);
-    ANDROID_API void syncAndDrawFrame(
+    ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
     ANDROID_API void destroyCanvasAndSurface();
 
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index e95707a..35a3eab 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -129,8 +129,7 @@
         , mDisplayEventReceiver(0)
         , mVsyncRequested(false)
         , mFrameCallbackTaskPending(false)
-        , mFrameCallbackTask(0)
-        , mFrameTime(0) {
+        , mFrameCallbackTask(0) {
     mFrameCallbackTask = new DispatchFrameCallbacks(this);
     mLooper = new Looper(false);
     run("RenderThread");
@@ -193,7 +192,7 @@
     nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver);
     if (vsyncEvent > 0) {
         mVsyncRequested = false;
-        mFrameTime = vsyncEvent;
+        mTimeLord.vsyncReceived(vsyncEvent);
         if (!mFrameCallbackTaskPending) {
             mFrameCallbackTaskPending = true;
             //queueDelayed(mFrameCallbackTask, DISPATCH_FRAME_CALLBACKS_DELAY);
@@ -209,7 +208,7 @@
     mFrameCallbacks.swap(callbacks);
 
     for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end(); it++) {
-        (*it)->doFrame(mFrameTime);
+        (*it)->doFrame();
     }
 }
 
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index b93dfd6..215d294 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -28,6 +28,8 @@
 #include <utils/Singleton.h>
 #include <utils/Thread.h>
 
+#include "TimeLord.h"
+
 namespace android {
 class DisplayEventReceiver;
 
@@ -53,7 +55,7 @@
 // Mimics android.view.Choreographer.FrameCallback
 class IFrameCallback {
 public:
-    virtual void doFrame(nsecs_t frameTimeNanos) = 0;
+    virtual void doFrame() = 0;
 
 protected:
     ~IFrameCallback() {}
@@ -71,6 +73,8 @@
     void postFrameCallback(IFrameCallback* callback);
     void removeFrameCallback(IFrameCallback* callback);
 
+    TimeLord& timeLord() { return mTimeLord; }
+
 protected:
     virtual bool threadLoop();
 
@@ -102,7 +106,8 @@
     std::set<IFrameCallback*> mFrameCallbacks;
     bool mFrameCallbackTaskPending;
     DispatchFrameCallbacks* mFrameCallbackTask;
-    nsecs_t mFrameTime;
+
+    TimeLord mTimeLord;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
new file mode 100644
index 0000000..758d96e
--- /dev/null
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -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.
+ */
+#include "TimeLord.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+TimeLord::TimeLord()
+        : mFrameIntervalNanos(0)
+        , mFrameTimeNanos(0) {
+}
+
+void TimeLord::vsyncReceived(nsecs_t vsync) {
+    if (vsync > mFrameTimeNanos) {
+        mFrameTimeNanos = vsync;
+    }
+}
+
+nsecs_t TimeLord::frameTimeMs() {
+    // Logic copied from Choreographer.java
+    nsecs_t now = systemTime(CLOCK_MONOTONIC);
+    nsecs_t jitterNanos = now - mFrameTimeNanos;
+    if (jitterNanos >= mFrameIntervalNanos) {
+        nsecs_t lastFrameOffset = jitterNanos % mFrameIntervalNanos;
+        mFrameTimeNanos = now - lastFrameOffset;
+    }
+    return nanoseconds_to_milliseconds(mFrameTimeNanos);
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
new file mode 100644
index 0000000..52c6d9e
--- /dev/null
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -0,0 +1,49 @@
+/*
+ * 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 TIMELORD_H
+#define TIMELORD_H
+
+#include <utils/Timers.h>
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class RenderThread;
+
+// This class serves as a helper to filter & manage frame times from multiple sources
+// ensuring that time flows linearly and smoothly
+class TimeLord {
+public:
+    void setFrameInterval(nsecs_t intervalNanos) { mFrameIntervalNanos = intervalNanos; }
+    void vsyncReceived(nsecs_t vsync);
+    nsecs_t frameTimeMs();
+
+private:
+    friend class RenderThread;
+
+    TimeLord();
+    ~TimeLord() {}
+
+    nsecs_t mFrameIntervalNanos;
+    nsecs_t mFrameTimeNanos;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* TIMELORD_H */
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
new file mode 100644
index 0000000..14a3ec0
--- /dev/null
+++ b/libs/hwui/utils/Macros.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MACROS_H
+#define MACROS_H
+
+#define PREVENT_COPY_AND_ASSIGN(Type) \
+    private: \
+        Type(const Type&); \
+        void operator=(const Type&)
+
+
+#endif /* MACROS_H */
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index ad0d459..6b2a247 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -32,11 +32,13 @@
     /** Default audio data format */
     public static final int ENCODING_DEFAULT = 1;
 
-    // These two values must be kept in sync with core/jni/android_media_AudioFormat.h
+    // These values must be kept in sync with core/jni/android_media_AudioFormat.h
     /** Audio data format: PCM 16 bit per sample. Guaranteed to be supported by devices. */
     public static final int ENCODING_PCM_16BIT = 2;
     /** Audio data format: PCM 8 bit per sample. Not guaranteed to be supported by devices. */
     public static final int ENCODING_PCM_8BIT = 3;
+    /** @hide Candidate for public API */
+    public static final int ENCODING_PCM_FLOAT = 4;
 
     /** Invalid audio channel configuration */
     /** @deprecated use CHANNEL_INVALID instead  */
@@ -139,4 +141,19 @@
     public static final int CHANNEL_IN_FRONT_BACK = CHANNEL_IN_FRONT | CHANNEL_IN_BACK;
     // CHANNEL_IN_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_IN_ALL
 
+    /** @hide */
+    public static int getBytesPerSample(int audioFormat)
+    {
+        switch (audioFormat) {
+        case ENCODING_PCM_8BIT:
+            return 1;
+        case ENCODING_PCM_16BIT:
+        case ENCODING_DEFAULT:
+            return 2;
+        case ENCODING_INVALID:
+        default:
+            throw new IllegalArgumentException("Bad audio format " + audioFormat);
+        }
+    }
+
 }
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index a4891f8..384e120 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -319,7 +319,7 @@
         // NB: this section is only valid with PCM data.
         // To update when supporting compressed formats
         int frameSizeInBytes = mChannelCount
-            * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
+            * (AudioFormat.getBytesPerSample(mAudioFormat));
         if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
             throw new IllegalArgumentException("Invalid audio buffer size.");
         }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 17840f2..1899685 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -518,7 +518,7 @@
         // NB: this section is only valid with PCM data.
         //     To update when supporting compressed formats
         int frameSizeInBytes = mChannelCount
-                * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
+                * (AudioFormat.getBytesPerSample(mAudioFormat));
         if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
             throw new IllegalArgumentException("Invalid audio buffer size.");
         }
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index bd91fc5..7735e78 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -169,9 +169,11 @@
                             
             native_setup(new WeakReference<JetPlayer>(this),
                     JetPlayer.getMaxTracks(),
-                    // bytes to frame conversion: sample format is ENCODING_PCM_16BIT, 2 channels
+                    // bytes to frame conversion:
                     // 1200 == minimum buffer size in frames on generation 1 hardware
-                    Math.max(1200, buffSizeInBytes / 4));
+                    Math.max(1200, buffSizeInBytes /
+                            (AudioFormat.getBytesPerSample(AudioFormat.ENCODING_PCM_16BIT) *
+                            2 /*channels*/)));
         }
     }
     
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/session/MediaMetadata.java b/media/java/android/media/session/MediaMetadata.java
index 56bdf68..8a8af45 100644
--- a/media/java/android/media/session/MediaMetadata.java
+++ b/media/java/android/media/session/MediaMetadata.java
@@ -295,6 +295,15 @@
     }
 
     /**
+     * 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.
      *
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 26eb9c4..3254e5d 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -225,6 +225,20 @@
     }
 
     @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
     public int describeContents() {
         return 0;
     }
diff --git a/packages/Keyguard/res/layout/keyguard_bouncer.xml b/packages/Keyguard/res/layout/keyguard_bouncer.xml
index 8716ebc..975a139 100644
--- a/packages/Keyguard/res/layout/keyguard_bouncer.xml
+++ b/packages/Keyguard/res/layout/keyguard_bouncer.xml
@@ -19,7 +19,7 @@
     android:layout_height="match_parent">
 
     <View android:id="@+id/bouncer_background"
-        android:background="#aa000000"
+        android:background="#cc000000"
         android:clickable="true"
         android:layout_width="match_parent"
         android:layout_height="match_parent"/>
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/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/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_camera_alt_24dp.png b/packages/SystemUI/res/drawable-hdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..253c73792
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-hdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..a6a6448
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_camera.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_camera.png
deleted file mode 100644
index c6f03c4..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_camera.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_camera_alt_24dp.png b/packages/SystemUI/res/drawable-mdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..ee1187b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-mdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..2286bb4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_camera.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_camera.png
deleted file mode 100644
index 1c2d7aa..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_camera.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_camera_alt_24dp.png b/packages/SystemUI/res/drawable-xhdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..268eba0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-xhdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..cd9ff60
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_camera.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_camera.png
deleted file mode 100644
index fbd4d6b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_camera.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_camera_alt_24dp.png b/packages/SystemUI/res/drawable-xxhdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..9175118
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-xxhdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..3c546e5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_camera.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_camera.png
deleted file mode 100644
index 86df881..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_camera.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_camera_alt_24dp.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..20e26b8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..4f7da0a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 809adcd..ec5acba 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -22,15 +22,29 @@
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     >
-    <com.android.systemui.statusbar.policy.KeyButtonView
+    <com.android.systemui.statusbar.phone.SwipeAffordanceView
         android:id="@+id/camera_button"
-        android:layout_height="80dp"
-        android:layout_width="80dp"
-        android:layout_gravity="bottom|right"
-        android:src="@drawable/ic_sysbar_camera"
+        android:layout_height="64dp"
+        android:layout_width="64dp"
+        android:layout_gravity="bottom|end"
+        android:tint="#ffffffff"
+        android:src="@drawable/ic_camera_alt_24dp"
         android:scaleType="center"
         android:contentDescription="@string/accessibility_camera_button"
-        systemui:glowBackground="@drawable/ic_sysbar_highlight_land" />
+        systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+        systemui:swipeDirection="start"/>
+
+    <com.android.systemui.statusbar.phone.SwipeAffordanceView
+        android:id="@+id/phone_button"
+        android:layout_height="64dp"
+        android:layout_width="64dp"
+        android:layout_gravity="bottom|start"
+        android:tint="#ffffffff"
+        android:src="@drawable/ic_phone_24dp"
+        android:scaleType="center"
+        android:contentDescription="@string/accessibility_phone_button"
+        systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+        systemui:swipeDirection="end"/>
 
     <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
         android:id="@+id/keyguard_indication_text"
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/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
index bf01a8d..7cf711a 100644
--- a/packages/SystemUI/res/values-sw720dp/config.xml
+++ b/packages/SystemUI/res/values-sw720dp/config.xml
@@ -32,5 +32,8 @@
 
     <!-- Min alpha % that recent items will fade to while being dismissed -->
     <integer name="config_recent_item_min_alpha">0</integer>
+
+    <!-- Transposes the search bar layout in landscape -->
+    <bool name="recents_transpose_search_layout_with_orientation">false</bool>
 </resources>
 
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 734abdc..f5674d2 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -45,6 +45,12 @@
     <declare-styleable name="BatteryMeterView">
         <attr name="frameColor" format="color" />
     </declare-styleable>
+    <declare-styleable name="SwipeAffordanceView">
+        <attr name="swipeDirection" format="enum">
+            <enum name="start" value="0" />
+            <enum name="end" value="1" />
+        </attr>
+    </declare-styleable>
     <attr name="orientation">
         <enum name="horizontal" value="0" />
         <enum name="vertical" value="1" />
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 722ca15..c3ccb59 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -115,12 +115,16 @@
     <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. -->
     <integer name="recents_max_task_stack_view_dim">96</integer>
+    <!-- Transposes the search bar layout in landscape -->
+    <bool name="recents_transpose_search_layout_with_orientation">true</bool>
 
     <!-- Whether to enable KeyguardService or not -->
     <bool name="config_enableKeyguardService">true</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2f2914c..d763bd6 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -227,14 +227,17 @@
     <!-- The radius of the rounded corners on a task view. -->
     <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
 
+    <!-- The min translation in the Z index for the last task. -->
+    <dimen name="recents_task_view_z_min">3dp</dimen>
+
+    <!-- The translation in the Z index for each task above the last task. -->
+    <dimen name="recents_task_view_z_increment">5dp</dimen>
+
     <!-- The amount of space a user has to scroll to dismiss any info panes. -->
     <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. -->
@@ -261,8 +264,8 @@
     <!-- Width of the zen mode interstitial dialog. -->
     <dimen name="zen_mode_dialog_width">320dp</dimen>
 
-    <!-- Camera affordance drag distance -->
-    <dimen name="camera_drag_distance">100dp</dimen>
+    <!-- Lockscreen affordance drag distance for camera and phone. -->
+    <dimen name="affordance_drag_distance">100dp</dimen>
 
     <dimen name="quick_settings_tmp_scrim_stroke_width">8dp</dimen>
     <dimen name="quick_settings_tmp_scrim_text_size">30dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b4a13d4..3f0a60f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -196,6 +196,8 @@
     <string name="accessibility_search_light">Search</string>
     <!-- Content description of the camera button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_camera_button">Camera</string>
+    <!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_button">Phone</string>
 
     <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_ime_switch_button">Switch input method button.</string>
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/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index f2e322d..396cb14 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -64,6 +64,17 @@
                 mSingleCountFirstTaskRect.offset(0, (int) statusBarHeight);
                 mMultipleCountFirstTaskRect = replyData.getParcelable(KEY_MULTIPLE_TASK_STACK_RECT);
                 mMultipleCountFirstTaskRect.offset(0, (int) statusBarHeight);
+                Console.log(Constants.DebugFlags.App.RecentsComponent,
+                        "[RecentsComponent|RecentsMessageHandler|handleMessage]",
+                        "singleTaskRect: " + mSingleCountFirstTaskRect +
+                        " multipleTaskRect: " + mMultipleCountFirstTaskRect);
+
+                // If we had the update the animation rects as a result of onServiceConnected, then
+                // we check for whether we need to toggle the recents here.
+                if (mToggleRecentsUponServiceBound) {
+                    startAlternateRecentsActivity();
+                    mToggleRecentsUponServiceBound = false;
+                }
             }
         }
     }
@@ -78,11 +89,16 @@
             mService = new Messenger(service);
             mServiceIsBound = true;
 
-            // Toggle recents if this service connection was triggered by hitting the recents button
-            if (mToggleRecentsUponServiceBound) {
-                startAlternateRecentsActivity();
+            if (hasValidTaskRects()) {
+                // Toggle recents if this new service connection was triggered by hitting recents
+                if (mToggleRecentsUponServiceBound) {
+                    startAlternateRecentsActivity();
+                    mToggleRecentsUponServiceBound = false;
+                }
+            } else {
+                // Otherwise, update the animation rects before starting the recents if requested
+                updateAnimationRects();
             }
-            mToggleRecentsUponServiceBound = false;
         }
 
         @Override
@@ -191,6 +207,26 @@
     }
 
     public void onConfigurationChanged(Configuration newConfig) {
+        updateAnimationRects();
+    }
+
+    /** Binds to the recents implementation */
+    private void bindToRecentsService(boolean toggleRecentsUponConnection) {
+        mToggleRecentsUponServiceBound = toggleRecentsUponConnection;
+        Intent intent = new Intent();
+        intent.setClassName(sRecentsPackage, sRecentsService);
+        mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+    }
+
+    /** Returns whether we have valid task rects to animate to. */
+    boolean hasValidTaskRects() {
+        return mSingleCountFirstTaskRect != null && mSingleCountFirstTaskRect.width() > 0 &&
+                mSingleCountFirstTaskRect.height() > 0 && mMultipleCountFirstTaskRect != null &&
+                mMultipleCountFirstTaskRect.width() > 0 && mMultipleCountFirstTaskRect.height() > 0;
+    }
+
+    /** Updates each of the task animation rects. */
+    void updateAnimationRects() {
         if (mServiceIsBound) {
             Resources res = mContext.getResources();
             int statusBarHeight = res.getDimensionPixelSize(
@@ -216,14 +252,6 @@
         }
     }
 
-    /** Binds to the recents implementation */
-    private void bindToRecentsService(boolean toggleRecentsUponConnection) {
-        mToggleRecentsUponServiceBound = toggleRecentsUponConnection;
-        Intent intent = new Intent();
-        intent.setClassName(sRecentsPackage, sRecentsService);
-        mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
-    }
-
     /** Loads the first task thumbnail */
     Bitmap loadFirstTaskThumbnail() {
         SystemServicesProxy ssp = mSystemServicesProxy;
@@ -300,6 +328,49 @@
         return SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
     }
 
+    /** Creates the activity options for a thumbnail transition. */
+    ActivityOptions getThumbnailTransitionActivityOptions(Rect taskRect) {
+        // Loading from thumbnail
+        Bitmap thumbnail;
+        Bitmap firstThumbnail = loadFirstTaskThumbnail();
+        if (firstThumbnail != null) {
+            // Create the thumbnail
+            thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
+                    Bitmap.Config.ARGB_8888);
+            int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
+            Canvas c = new Canvas(thumbnail);
+            c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
+                    new Rect(0, 0, taskRect.width(), taskRect.height()), null);
+            c.setBitmap(null);
+            // Recycle the old thumbnail
+            firstThumbnail.recycle();
+        } else {
+            // Load the thumbnail from the screenshot if can't get one from the system
+            WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+            Display display = wm.getDefaultDisplay();
+            Bitmap screenshot = takeScreenshot(display);
+            if (screenshot != null) {
+                Resources res = mContext.getResources();
+                int size = Math.min(screenshot.getWidth(), screenshot.getHeight());
+                int statusBarHeight = res.getDimensionPixelSize(
+                        com.android.internal.R.dimen.status_bar_height);
+                thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
+                        Bitmap.Config.ARGB_8888);
+                Canvas c = new Canvas(thumbnail);
+                c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight +
+                        size), new Rect(0, 0, taskRect.width(), taskRect.height()), null);
+                c.setBitmap(null);
+                // Recycle the temporary screenshot
+                screenshot.recycle();
+            } else {
+                return null;
+            }
+        }
+
+        return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView, thumbnail,
+                taskRect.left, taskRect.top, null);
+    }
+
     /** Starts the recents activity */
     void startAlternateRecentsActivity() {
         // If the user has toggled it too quickly, then just eat up the event here (it's better than
@@ -351,47 +422,28 @@
         // number of items in the list.
         List<ActivityManager.RecentTaskInfo> recentTasks =
                 ssp.getRecentTasks(4, UserHandle.CURRENT.getIdentifier());
-        boolean hasMultipleTasks = hasMultipleRecentsTask(recentTasks);
+        Rect taskRect = hasMultipleRecentsTask(recentTasks) ? mMultipleCountFirstTaskRect :
+                mSingleCountFirstTaskRect;
         boolean isTaskExcludedFromRecents = isTopTaskExcludeFromRecents(recentTasks);
-        Rect taskRect = hasMultipleTasks ? mMultipleCountFirstTaskRect : mSingleCountFirstTaskRect;
-        if (!isTopTaskHome && !isTaskExcludedFromRecents &&
-                (taskRect != null) && (taskRect.width() > 0) && (taskRect.height() > 0)) {
-            // Loading from thumbnail
-            Bitmap thumbnail;
-            Bitmap firstThumbnail = loadFirstTaskThumbnail();
-            if (firstThumbnail != null) {// Create the thumbnail
-                thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
-                        Bitmap.Config.ARGB_8888);
-                int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
-                Canvas c = new Canvas(thumbnail);
-                c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
-                        new Rect(0, 0, taskRect.width(), taskRect.height()), null);
-                c.setBitmap(null);
-                // Recycle the old thumbnail
-                firstThumbnail.recycle();
-            } else {
-                // Load the thumbnail from the screenshot if can't get one from the system
-                WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-                Display display = wm.getDefaultDisplay();
-                Bitmap screenshot = takeScreenshot(display);
-                Resources res = mContext.getResources();
-                int size = Math.min(screenshot.getWidth(), screenshot.getHeight());
-                int statusBarHeight = res.getDimensionPixelSize(
-                        com.android.internal.R.dimen.status_bar_height);
-                thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
-                        Bitmap.Config.ARGB_8888);
-                Canvas c = new Canvas(thumbnail);
-                c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight + size),
-                        new Rect(0, 0, taskRect.width(), taskRect.height()), null);
-                c.setBitmap(null);
-                // Recycle the temporary screenshot
-                screenshot.recycle();
-            }
+        boolean useThumbnailTransition = !isTopTaskHome && !isTaskExcludedFromRecents &&
+                hasValidTaskRects();
 
-            ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView,
-                    thumbnail, taskRect.left, taskRect.top, null);
-            startAlternateRecentsActivity(opts, true);
-        } else {
+        if (useThumbnailTransition) {
+            // Try starting with a thumbnail transition
+            ActivityOptions opts = getThumbnailTransitionActivityOptions(taskRect);
+            if (opts != null) {
+                startAlternateRecentsActivity(opts, true);
+            } else {
+                // Fall through below to the non-thumbnail transition
+                useThumbnailTransition = false;
+            }
+        }
+
+        // If there is no thumbnail transition, then just use a generic transition
+        // XXX: This should be different between home and from a recents-excluded app, perhaps the
+        //      recents-excluded app should still show up in recents, when the app is in the
+        //      foreground
+        if (!useThumbnailTransition) {
             ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
                     R.anim.recents_from_launcher_enter,
                     R.anim.recents_from_launcher_exit);
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 a996c1a..90ea873 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -28,8 +28,9 @@
         public static class App {
             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;
@@ -85,11 +91,8 @@
             public static final int TaskStackOverscrollRange = 150;
             public static final int FilterStartDelay = 25;
 
-            // The amount to inverse scale the movement if we are overscrolling
-            public static final float TouchOverscrollScaleFactor = 3f;
-
             // The padding will be applied to the smallest dimension, and then applied to all sides
-            public static final float StackPaddingPct = 0.15f;
+            public static final float StackPaddingPct = 0.1f;
             // The overlap height relative to the task height
             public static final float StackOverlapPct = 0.65f;
             // The height of the peek space relative to the stack height
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..d1a3954 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,28 @@
     public Rect systemInsets = new Rect();
     public Rect displayRect = new Rect();
 
+    boolean isLandscape;
+    boolean transposeSearchLayoutWithOrientation;
+    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 taskViewTranslationZMinPx;
+    public int taskViewTranslationZIncrementPx;
     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,8 +84,10 @@
         DisplayMetrics dm = res.getDisplayMetrics();
         mDisplayMetrics = dm;
 
-        boolean isLandscape = res.getConfiguration().orientation ==
+        isLandscape = res.getConfiguration().orientation ==
                 Configuration.ORIENTATION_LANDSCAPE;
+        transposeSearchLayoutWithOrientation =
+                res.getBoolean(R.bool.recents_transpose_search_layout_with_orientation);
         Console.log(Constants.DebugFlags.UI.MeasureAndLayout,
                 "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
                 Console.AnsiGreen);
@@ -87,6 +101,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);
@@ -94,9 +110,24 @@
                 res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
         taskViewRoundedCornerRadiusPx =
                 res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
+        taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
+        taskViewTranslationZIncrementPx =
+                res.getDimensionPixelSize(R.dimen.recents_task_view_z_increment);
         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 +135,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 && transposeSearchLayoutWithOrientation) {
+                // 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 && transposeSearchLayoutWithOrientation) {
+            // 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..c3b8a20 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,23 +49,32 @@
  */
 public class SystemServicesProxy {
     ActivityManager mAm;
+    AppWidgetManager mAwm;
     PackageManager mPm;
     IPackageManager mIpm;
     UserManager mUm;
     SearchManager mSm;
     String mPackage;
+    ComponentName mAssistComponent;
 
     Bitmap mDummyIcon;
 
     /** 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();
         mSm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
         mPackage = context.getPackageName();
 
+        // Resolve the assist intent
+        Intent assist = mSm.getAssistIntent(context, false);
+        if (assist != null) {
+            mAssistComponent = assist.getComponent();
+        }
+
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
             // Create a dummy icon
             mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
@@ -91,10 +101,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 +116,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 +175,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 +190,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 +238,54 @@
         return icon;
     }
 
+    /**
+     * Resolves and binds the search app widget that is to appear in the recents.
+     */
+    public Pair<Integer, AppWidgetProviderInfo> bindSearchAppWidget(AppWidgetHost host) {
+        if (mAwm == null) return null;
+        if (mAssistComponent == null) return null;
+
+        // Find the first Recents widget from the same package as the global assist activity
+        List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders(
+                AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+        AppWidgetProviderInfo searchWidgetInfo = null;
+        for (AppWidgetProviderInfo info : widgets) {
+            if (info.provider.getPackageName().equals(mAssistComponent.getPackageName())) {
+                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);
+    }
 
     /**
-     * Composes an intent to launch the global search activity.
+     * Returns the app widget info for the specified app widget id.
      */
-    public Intent getGlobalSearchIntent(Rect sourceBounds) {
-        if (mSm == null) return null;
+    public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
+        if (mAwm == null) return null;
 
-        // Try and get the global search activity
-        ComponentName globalSearchActivity = mSm.getGlobalSearchActivity();
-        if (globalSearchActivity == null) return null;
+        return mAwm.getAppWidgetInfo(appWidgetId);
+    }
 
-        // Bundle the source of the search
-        Bundle appSearchData = new Bundle();
-        appSearchData.putString("source", mPackage);
+    /**
+     * Destroys the specified app widget.
+     */
+    public void unbindSearchAppWidget(AppWidgetHost host, int appWidgetId) {
+        if (mAwm == null) return;
 
-        // 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;
+        // 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..c6c29a6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
@@ -20,16 +20,21 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.graphics.Canvas;
 import android.graphics.Path;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.drawable.TouchFeedbackDrawable;
 import android.util.AttributeSet;
 import android.widget.Button;
 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 +148,25 @@
                 .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);
+            // Workaround: The button currently doesn't support setting a custom background tint
+            // not defined in the theme.  Just lower the alpha on the button to make it blend more
+            // into the background.
+            if (mAppInfoButton.getBackground() instanceof TouchFeedbackDrawable) {
+                TouchFeedbackDrawable d = (TouchFeedbackDrawable) mAppInfoButton.getBackground();
+                if (d != null) {
+                    d.setAlpha(96);
+                }
+            }
+        } 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 0a8e76f..ce43b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -395,12 +395,20 @@
         return false;
     }
 
-    /** Returns whether the specified scroll is out of bounds */
-    boolean isScrollOutOfBounds(int scroll) {
-        return (scroll < mMinScroll) || (scroll > mMaxScroll);
+
+    /** Returns the amount that the scroll is out of bounds */
+    int getScrollAmountOutOfBounds(int scroll) {
+        if (scroll < mMinScroll) {
+            return mMinScroll - scroll;
+        } else if (scroll > mMaxScroll) {
+            return scroll - mMaxScroll;
+        }
+        return 0;
     }
+
+    /** Returns whether the specified scroll is out of bounds */
     boolean isScrollOutOfBounds() {
-        return isScrollOutOfBounds(getStackScroll());
+        return getScrollAmountOutOfBounds(getStackScroll()) != 0;
     }
 
     /** Updates the min and max virtual scroll bounds */
@@ -547,7 +555,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,12 +563,13 @@
         // 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);
         int padding = (int) (Constants.Values.TaskStackView.StackPaddingPct * smallestDimension / 2f);
         if (Constants.DebugFlags.App.EnableSearchButton) {
-            // Don't need to pad the top since we have some padding on the search bar already
+            mStackRect.top += padding;
             mStackRect.left += padding;
             mStackRect.right -= padding;
             mStackRect.bottom -= padding;
@@ -582,6 +591,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 +606,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 +646,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]",
@@ -1284,9 +1305,13 @@
                 }
                 if (mIsScrolling) {
                     int curStackScroll = mSv.getStackScroll();
-                    if (mSv.isScrollOutOfBounds(curStackScroll + deltaY)) {
-                        // Scale the touch if we are overscrolling
-                        deltaY /= Constants.Values.TaskStackView.TouchOverscrollScaleFactor;
+                    int overScrollAmount = mSv.getScrollAmountOutOfBounds(curStackScroll + deltaY);
+                    if (overScrollAmount != 0) {
+                        // Bound the overscroll to a fixed amount, and inversely scale the y-movement
+                        // relative to how close we are to the max overscroll
+                        float maxOverScroll = mSv.mTaskRect.height() / 3f;
+                        deltaY = Math.round(deltaY * (1f - (Math.min(maxOverScroll, overScrollAmount)
+                                / maxOverScroll)));
                     }
                     mSv.setStackScroll(curStackScroll + deltaY);
                     if (mSv.isScrollOutOfBounds()) {
@@ -1306,6 +1331,7 @@
                 if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
                     // Enable HW layers on the stack
                     mSv.addHwLayersRefCount("flingScroll");
+                    // XXX: Make this animation a function of the velocity AND distance
                     int overscrollRange = (int) (Math.min(1f,
                             Math.abs((float) velocity / mMaximumVelocity)) *
                             Constants.Values.TaskStackView.TaskStackOverscrollRange);
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..801de24 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -20,6 +20,7 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.Outline;
 import android.graphics.Path;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -33,7 +34,6 @@
 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;
 
 
@@ -108,6 +108,11 @@
         mRoundedRectClipPath.reset();
         mRoundedRectClipPath.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()),
                 radius, radius, Path.Direction.CW);
+
+        // Update the outline
+        Outline o = new Outline();
+        o.setRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), radius);
+        setOutline(o);
     }
 
     @Override
@@ -134,14 +139,20 @@
     /** Synchronizes this view's properties with the task's transform */
     void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
                                              TaskViewTransform toTransform, int duration) {
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        int minZ = config.taskViewTranslationZMinPx;
+        int incZ = config.taskViewTranslationZIncrementPx;
+
         if (duration > 0) {
             if (animateFromTransform != null) {
                 setTranslationY(animateFromTransform.translationY);
+                setTranslationZ(Math.max(minZ, minZ + (animateFromTransform.t * incZ)));
                 setScaleX(animateFromTransform.scale);
                 setScaleY(animateFromTransform.scale);
                 setAlpha(animateFromTransform.alpha);
             }
             animate().translationY(toTransform.translationY)
+                    .translationZ(Math.max(minZ, minZ + (toTransform.t * incZ)))
                     .scaleX(toTransform.scale)
                     .scaleY(toTransform.scale)
                     .alpha(toTransform.alpha)
@@ -157,6 +168,7 @@
                     .start();
         } else {
             setTranslationY(toTransform.translationY);
+            setTranslationZ(Math.max(minZ, minZ + (toTransform.t * incZ)));
             setScaleX(toTransform.scale);
             setScaleY(toTransform.scale);
             setAlpha(toTransform.alpha);
@@ -169,6 +181,7 @@
     void resetViewProperties() {
         setTranslationX(0f);
         setTranslationY(0f);
+        setTranslationZ(0f);
         setScaleX(1f);
         setScaleY(1f);
         setAlpha(1f);
@@ -197,18 +210,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 +223,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 +351,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);
@@ -376,7 +376,7 @@
     @Override
     public void onClick(View v) {
         if (v == mInfoView) {
-            // Do nothing
+            hideInfoPane();
         } else if (v == mBarView.mApplicationIcon) {
             mCb.onTaskIconClicked(this);
         } else if (v == mInfoView.mAppInfoButton) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index edf54d1..2c7464a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -773,8 +773,8 @@
 
         PendingIntent contentIntent = sbn.getNotification().contentIntent;
         if (contentIntent != null) {
-            final View.OnClickListener listener = makeClicker(contentIntent,
-                    sbn.getPackageName(), sbn.getTag(), sbn.getId(), isHeadsUp, sbn.getUserId());
+            final View.OnClickListener listener = makeClicker(contentIntent, sbn.getKey(),
+                    isHeadsUp);
             row.setOnClickListener(listener);
         } else {
             row.setOnClickListener(null);
@@ -884,27 +884,20 @@
         return true;
     }
 
-    public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag,
-            int id, boolean forHun, int userId) {
-        return new NotificationClicker(intent, pkg, tag, id, forHun, userId);
+    public NotificationClicker makeClicker(PendingIntent intent, String notificationKey,
+            boolean forHun) {
+        return new NotificationClicker(intent, notificationKey, forHun);
     }
 
     protected class NotificationClicker implements View.OnClickListener {
         private PendingIntent mIntent;
-        private String mPkg;
-        private String mTag;
-        private int mId;
+        private final String mNotificationKey;
         private boolean mIsHeadsUp;
-        private int mUserId;
 
-        public NotificationClicker(PendingIntent intent, String pkg, String tag, int id,
-                boolean forHun, int userId) {
+        public NotificationClicker(PendingIntent intent, String notificationKey, boolean forHun) {
             mIntent = intent;
-            mPkg = pkg;
-            mTag = tag;
-            mId = id;
+            mNotificationKey = notificationKey;
             mIsHeadsUp = forHun;
-            mUserId = userId;
         }
 
         public void onClick(View v) {
@@ -940,7 +933,7 @@
                 if (mIsHeadsUp) {
                     mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP);
                 }
-                mBarService.onNotificationClick(mPkg, mTag, mId, mUserId);
+                mBarService.onNotificationClick(mNotificationKey);
             } catch (RemoteException ex) {
                 // system process is dead if we're here.
             }
@@ -1344,9 +1337,8 @@
         // update the contentIntent
         final PendingIntent contentIntent = notification.getNotification().contentIntent;
         if (contentIntent != null) {
-            final View.OnClickListener listener = makeClicker(contentIntent,
-                    notification.getPackageName(), notification.getTag(), notification.getId(),
-                    isHeadsUp, notification.getUserId());
+            final View.OnClickListener listener = makeClicker(contentIntent, notification.getKey(),
+                    isHeadsUp);
             entry.row.setOnClickListener(listener);
         } else {
             entry.row.setOnClickListener(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 232795a..169521d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.FrameLayout;
 
@@ -44,6 +45,19 @@
         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.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
new file mode 100644
index 0000000..5bc7e5a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -0,0 +1,28 @@
+/*
+ * 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.phone;
+
+import android.content.Intent;
+
+/**
+ * An interface to start activities. This is used to as a callback from the views to
+ * {@link PhoneStatusBar} to allow custom handling for starting the activity, i.e. dismissing the
+ * Keyguard.
+ */
+public interface ActivityStarter {
+    public void startActivity(Intent intent);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 3cc22ef..58b3f2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -42,14 +43,18 @@
  * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
  * text.
  */
-public class KeyguardBottomAreaView extends FrameLayout {
+public class KeyguardBottomAreaView extends FrameLayout
+        implements SwipeAffordanceView.AffordanceListener {
 
     final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
 
-    private View mCameraButton;
-    private float mCameraDragDistance;
+    private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
+
+    private SwipeAffordanceView mCameraButton;
+    private SwipeAffordanceView mPhoneButton;
+
     private PowerManager mPowerManager;
-    private int mScaledTouchSlop;
+    private ActivityStarter mActivityStarter;
 
     public KeyguardBottomAreaView(Context context) {
         super(context);
@@ -71,20 +76,37 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mCameraButton = findViewById(R.id.camera_button);
+        mCameraButton = (SwipeAffordanceView) findViewById(R.id.camera_button);
+        mPhoneButton = (SwipeAffordanceView) findViewById(R.id.phone_button);
+        mCameraButton.setAffordanceListener(this);
+        mPhoneButton.setAffordanceListener(this);
         watchForDevicePolicyChanges();
         watchForAccessibilityChanges();
         updateCameraVisibility();
-        mCameraDragDistance = getResources().getDimension(R.dimen.camera_drag_distance);
-        mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        updatePhoneVisibility();
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
     }
 
+    public void setActivityStarter(ActivityStarter activityStarter) {
+        mActivityStarter = activityStarter;
+    }
+
     private void updateCameraVisibility() {
         boolean visible = !isCameraDisabledByDpm();
         mCameraButton.setVisibility(visible ? View.VISIBLE : View.GONE);
     }
 
+    private void updatePhoneVisibility() {
+        boolean visible = isPhoneVisible();
+        mPhoneButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    private boolean isPhoneVisible() {
+        PackageManager pm = mContext.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
+                && pm.resolveActivity(PHONE_INTENT, 0) != null;
+    }
+
     private boolean isCameraDisabledByDpm() {
         final DevicePolicyManager dpm =
                 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
@@ -136,15 +158,8 @@
     }
 
     private void enableAccessibility(boolean touchExplorationEnabled) {
-
-        // Add a touch handler or accessibility click listener for camera button.
-        if (touchExplorationEnabled) {
-            mCameraButton.setOnTouchListener(null);
-            mCameraButton.setOnClickListener(mCameraClickListener);
-        } else {
-            mCameraButton.setOnTouchListener(mCameraTouchListener);
-            mCameraButton.setOnClickListener(null);
-        }
+        mCameraButton.enableAccessibility(touchExplorationEnabled);
+        mPhoneButton.enableAccessibility(touchExplorationEnabled);
     }
 
     private void launchCamera() {
@@ -153,80 +168,21 @@
                 UserHandle.CURRENT);
     }
 
-    private final OnClickListener mCameraClickListener = new OnClickListener() {
-        @Override
-        public void onClick(View v) {
+    private void launchPhone() {
+        mActivityStarter.startActivity(PHONE_INTENT);
+    }
+
+    @Override
+    public void onUserActivity(long when) {
+        mPowerManager.userActivity(when, false);
+    }
+
+    @Override
+    public void onActionPerformed(SwipeAffordanceView view) {
+        if (view == mCameraButton) {
             launchCamera();
+        } else if (view == mPhoneButton) {
+            launchPhone();
         }
-    };
-
-    private final OnTouchListener mCameraTouchListener = new OnTouchListener() {
-        private float mStartX;
-        private boolean mTouchSlopReached;
-        private boolean mSkipCancelAnimation;
-
-        @Override
-        public boolean onTouch(final View cameraButtonView, MotionEvent event) {
-            float realX = event.getRawX();
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_DOWN:
-                    mStartX = realX;
-                    mTouchSlopReached = false;
-                    mSkipCancelAnimation = false;
-                    break;
-                case MotionEvent.ACTION_MOVE:
-                    if (realX > mStartX) {
-                        realX = mStartX;
-                    }
-                    if (realX < mStartX - mCameraDragDistance) {
-                        cameraButtonView.setPressed(true);
-                        mPowerManager.userActivity(event.getEventTime(), false);
-                    } else {
-                        cameraButtonView.setPressed(false);
-                    }
-                    if (realX < mStartX - mScaledTouchSlop) {
-                        mTouchSlopReached = true;
-                    }
-                    cameraButtonView.setTranslationX(Math.max(realX - mStartX,
-                            -mCameraDragDistance));
-                    break;
-                case MotionEvent.ACTION_UP:
-                    if (realX < mStartX - mCameraDragDistance) {
-                        launchCamera();
-                        cameraButtonView.animate().x(-cameraButtonView.getWidth())
-                                .setInterpolator(new AccelerateInterpolator(2f)).withEndAction(
-                                new Runnable() {
-                                    @Override
-                                    public void run() {
-                                        cameraButtonView.setTranslationX(0);
-                                    }
-                                });
-                        mSkipCancelAnimation = true;
-                    }
-                    if (realX < mStartX - mScaledTouchSlop) {
-                        mTouchSlopReached = true;
-                    }
-                    if (!mTouchSlopReached) {
-                        mSkipCancelAnimation = true;
-                        cameraButtonView.animate().translationX(-mCameraDragDistance / 2).
-                                setInterpolator(new DecelerateInterpolator()).withEndAction(
-                                new Runnable() {
-                                    @Override
-                                    public void run() {
-                                        cameraButtonView.animate().translationX(0).
-                                                setInterpolator(new AccelerateInterpolator());
-                                    }
-                                });
-                    }
-                case MotionEvent.ACTION_CANCEL:
-                    cameraButtonView.setPressed(false);
-                    if (!mSkipCancelAnimation) {
-                        cameraButtonView.animate().translationX(0)
-                                .setInterpolator(new AccelerateInterpolator(2f));
-                    }
-                    break;
-            }
-            return true;
-        }
-    };
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 328a172..0cdca66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -623,9 +623,7 @@
                 mExpandedHeight = mMaxPanelHeight;
             }
         }
-        heightMeasureSpec = MeasureSpec.makeMeasureSpec(
-                getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
-        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
+        setMeasuredDimension(getMeasuredWidth(), getDesiredMeasureHeight());
     }
 
     protected int getDesiredMeasureHeight() {
@@ -705,11 +703,6 @@
      * @return the default implementation simply returns the maximum height.
      */
     protected int getMaxPanelHeight() {
-        if (mMaxPanelHeight <= 0) {
-            if (DEBUG) logf("Forcing measure() since mMaxPanelHeight=" + mMaxPanelHeight);
-            measure(MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY),
-                    MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY));
-        }
         return mMaxPanelHeight;
     }
 
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 0db6914..f945c79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -124,7 +124,7 @@
 import java.util.Collections;
 
 public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
-        DragDownHelper.OnDragDownListener {
+        DragDownHelper.OnDragDownListener, ActivityStarter {
     static final String TAG = "PhoneStatusBar";
     public static final boolean DEBUG = BaseStatusBar.DEBUG;
     public static final boolean SPEW = false;
@@ -236,7 +236,7 @@
     // top bar
     View mNotificationPanelHeader;
     View mKeyguardStatusView;
-    View mKeyguardBottomArea;
+    KeyguardBottomAreaView mKeyguardBottomArea;
     boolean mLeaveOpenOnKeyguardHide;
     KeyguardIndicationTextView mKeyguardIndicationTextView;
 
@@ -639,7 +639,9 @@
 
         mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
         mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
-        mKeyguardBottomArea = mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
+        mKeyguardBottomArea =
+                (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
+        mKeyguardBottomArea.setActivityStarter(this);
         mKeyguardIndicationTextView = (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
                 R.id.keyguard_indication_text);
         mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
@@ -1578,6 +1580,11 @@
         return new PhoneStatusBar.H();
     }
 
+    @Override
+    public void startActivity(Intent intent) {
+        startActivityDismissingKeyguard(intent, false);
+    }
+
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
@@ -1668,6 +1675,9 @@
     }
 
     public void animateCollapsePanels(int flags) {
+        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
+            return;
+        }
         if (SPEW) {
             Log.d(TAG, "animateCollapse():"
                     + " mExpandedVisible=" + mExpandedVisible
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 554892c..e24ddd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -205,10 +205,12 @@
         } 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());
     }
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 acc3a0b..4c9264d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -108,7 +108,9 @@
         boolean intercept = false;
         if (mNotificationPanel.isFullyExpanded()
                 && mStackScrollLayout.getVisibility() == View.VISIBLE
-                && mService.getBarState() != StatusBarState.KEYGUARD) {
+                && (mService.getBarState() == StatusBarState.SHADE
+                        || (mService.getBarState() == StatusBarState.SHADE_LOCKED
+                                && !mService.isBouncerShowing()))) {
             intercept = mExpandHelper.onInterceptTouchEvent(ev);
         } else if (mNotificationPanel.isFullyExpanded()
                 && mStackScrollLayout.getVisibility() == View.VISIBLE
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SwipeAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SwipeAffordanceView.java
new file mode 100644
index 0000000..049c5fc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SwipeAffordanceView.java
@@ -0,0 +1,222 @@
+/*
+ * 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.phone;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.Button;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.KeyButtonView;
+
+/**
+ * A swipeable button for affordances on the lockscreen. This is used for the camera and phone
+ * affordance.
+ */
+public class SwipeAffordanceView extends KeyButtonView {
+
+    private static final int SWIPE_DIRECTION_START = 0;
+    private static final int SWIPE_DIRECTION_END = 1;
+
+    private static final int SWIPE_DIRECTION_LEFT = 0;
+    private static final int SWIPE_DIRECTION_RIGHT = 1;
+
+    private AffordanceListener mListener;
+    private int mScaledTouchSlop;
+    private float mDragDistance;
+    private int mResolvedSwipeDirection;
+    private int mSwipeDirection;
+
+    public SwipeAffordanceView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SwipeAffordanceView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        TypedArray a = context.getTheme().obtainStyledAttributes(
+                attrs,
+                R.styleable.SwipeAffordanceView,
+                0, 0);
+        try {
+            mSwipeDirection = a.getInt(R.styleable.SwipeAffordanceView_swipeDirection, 0);
+        } finally {
+            a.recycle();
+        }
+    }
+
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        super.onRtlPropertiesChanged(layoutDirection);
+        if (!isLayoutRtl()) {
+            mResolvedSwipeDirection = mSwipeDirection;
+        } else {
+            mResolvedSwipeDirection = mSwipeDirection == SWIPE_DIRECTION_START
+                    ? SWIPE_DIRECTION_RIGHT
+                    : SWIPE_DIRECTION_LEFT;
+        }
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mDragDistance = getResources().getDimension(R.dimen.affordance_drag_distance);
+        mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+    }
+
+    public void enableAccessibility(boolean touchExplorationEnabled) {
+
+        // Add a touch handler or accessibility click listener for camera button.
+        if (touchExplorationEnabled) {
+            setOnTouchListener(null);
+            setOnClickListener(mClickListener);
+        } else {
+            setOnTouchListener(mTouchListener);
+            setOnClickListener(null);
+        }
+    }
+
+    public void setAffordanceListener(AffordanceListener listener) {
+        mListener = listener;
+    }
+
+    private void onActionPerformed() {
+        if (mListener != null) {
+            mListener.onActionPerformed(this);
+        }
+    }
+
+    private void onUserActivity(long when) {
+        if (mListener != null) {
+            mListener.onUserActivity(when);
+        }
+    }
+
+    private final OnClickListener mClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            onActionPerformed();
+        }
+    };
+
+    private final OnTouchListener mTouchListener = new OnTouchListener() {
+        private float mStartX;
+        private boolean mTouchSlopReached;
+        private boolean mSkipCancelAnimation;
+
+        @Override
+        public boolean onTouch(final View view, MotionEvent event) {
+            float realX = event.getRawX();
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_DOWN:
+                    mStartX = realX;
+                    mTouchSlopReached = false;
+                    mSkipCancelAnimation = false;
+                    break;
+                case MotionEvent.ACTION_MOVE:
+                    if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+                            ? realX > mStartX
+                            : realX < mStartX) {
+                        realX = mStartX;
+                    }
+                    if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+                            ? realX < mStartX - mDragDistance
+                            : realX > mStartX + mDragDistance) {
+                        view.setPressed(true);
+                        onUserActivity(event.getEventTime());
+                    } else {
+                        view.setPressed(false);
+                    }
+                    if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+                            ? realX < mStartX - mScaledTouchSlop
+                            : realX > mStartX + mScaledTouchSlop) {
+                        mTouchSlopReached = true;
+                    }
+                    view.setTranslationX(mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+                                    ? Math.max(realX - mStartX, -mDragDistance)
+                                    : Math.min(realX - mStartX, mDragDistance));
+                    break;
+                case MotionEvent.ACTION_UP:
+                    if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+                            ? realX < mStartX - mDragDistance
+                            : realX > mStartX + mDragDistance) {
+                        onActionPerformed();
+                        view.animate().x(mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+                                ? -view.getWidth()
+                                : ((View) view.getParent()).getWidth() + view.getWidth())
+                                .setInterpolator(new AccelerateInterpolator(2f)).withEndAction(
+                                new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        view.setTranslationX(0);
+                                    }
+                                });
+                        mSkipCancelAnimation = true;
+                    }
+                    if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+                            ? realX < mStartX - mScaledTouchSlop
+                            : realX > mStartX + mScaledTouchSlop) {
+                        mTouchSlopReached = true;
+                    }
+                    if (!mTouchSlopReached) {
+                        mSkipCancelAnimation = true;
+                        view.animate().translationX(mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+                                ? -mDragDistance / 2
+                                : mDragDistance / 2).
+                                setInterpolator(new DecelerateInterpolator()).withEndAction(
+                                new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        view.animate().translationX(0).
+                                                setInterpolator(new AccelerateInterpolator());
+                                    }
+                                });
+                    }
+                case MotionEvent.ACTION_CANCEL:
+                    view.setPressed(false);
+                    if (!mSkipCancelAnimation) {
+                        view.animate().translationX(0)
+                                .setInterpolator(new AccelerateInterpolator(2f));
+                    }
+                    break;
+            }
+            return true;
+        }
+    };
+
+    public interface AffordanceListener {
+
+        /**
+         * Called when the view would like to report user activity.
+         *
+         * @param when The timestamp of the user activity in {@link SystemClock#uptimeMillis} time
+         *             base.
+         */
+        void onUserActivity(long when);
+
+        /**
+         * Called when the action of the affordance has been performed.
+         */
+        void onActionPerformed(SwipeAffordanceView view);
+    }
+}
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/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 50e2a2e..b1fea03 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3560,15 +3560,7 @@
         swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
             @Override
             public void onDismissed(SwipeDismissLayout layout) {
-                Callback cb = getCallback();
-                if (cb != null) {
-                    try {
-                        cb.onWindowDismissed();
-                    } catch (AbstractMethodError e) {
-                        Log.e(TAG, "onWindowDismissed not implemented in " +
-                                cb.getClass().getSimpleName(), e);
-                    }
-                }
+                dispatchOnWindowDismissed();
             }
         });
         swipeDismiss.setOnSwipeProgressChangedListener(
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 761e580..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() {
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/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 5083d44..6fab37c2 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -65,6 +65,8 @@
 27501 notification_panel_hidden
 # when notifications are newly displayed on screen, or disappear from screen
 27510 notification_visibility_changed (newlyVisibleKeys|3),(noLongerVisibleKeys|3)
+# when a notification has been clicked
+27520 notification_clicked (key|3)
 
 # ---------------------------
 # Watchdog.java
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/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 9eaddbd..cbb8377 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;
 
     /**
@@ -5452,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);
@@ -6982,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;
@@ -7054,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;
@@ -7094,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;
@@ -7122,14 +7079,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) {
@@ -7197,13 +7174,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;
             }
         }
     }
@@ -7635,82 +7610,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
     // =========================================================
 
@@ -15305,8 +15204,8 @@
         // it when computing the final cached adj later.  Note that we don't need to
         // worry about this for max adj above, since max adj will always be used to
         // keep it out of the cached vaues.
-        adj = app.modifyRawOomAdj(adj);
-
+        app.curAdj = app.modifyRawOomAdj(adj);
+        app.curSchedGroup = schedGroup;
         app.curProcState = procState;
         app.foregroundActivities = foregroundActivities;
 
diff --git a/services/core/java/com/android/server/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..2e979d2 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();
     }
@@ -3169,7 +3119,7 @@
                 }
             }
             ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, null, userId);
-            if ((aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
+            if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
                 throw new SecurityException(
                         "Attempt to embed activity that has not set allowEmbedded=\"true\"");
             }
@@ -3288,9 +3238,9 @@
             } else {
                 mContainerState = CONTAINER_STATE_NO_SURFACE;
                 ((VirtualActivityDisplay) mActivityDisplay).setSurface(null);
-//                if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
-//                    mStack.startPausingLocked(false, true);
-//                }
+                if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
+                    mStack.startPausingLocked(false, true);
+                }
             }
 
             setSurfaceIfReady();
@@ -3300,6 +3250,11 @@
         }
 
         @Override
+        boolean isAttached() {
+            return mSurface != null && super.isAttached();
+        }
+
+        @Override
         void setDrawn() {
             synchronized (mService) {
                 mDrawn = true;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 83e8a4b..dd12a65 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -230,10 +230,10 @@
         }
     }
         
-    public void noteScreenOn() {
+    public void noteScreenState(int state) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteScreenOnLocked();
+            mStats.noteScreenStateLocked(state);
         }
     }
     
@@ -244,24 +244,19 @@
         }
     }
     
-    public void noteScreenOff() {
-        enforceCallingPermission();
-        synchronized (mStats) {
-            mStats.noteScreenOffLocked();
-        }
-    }
-
-    public void noteInputEvent() {
-        enforceCallingPermission();
-        mStats.noteInputEventAtomic();
-    }
-    
     public void noteUserActivity(int uid, int event) {
         enforceCallingPermission();
         synchronized (mStats) {
             mStats.noteUserActivityLocked(uid, event);
         }
     }
+    
+    public void noteInteractive(boolean interactive) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteInteractiveLocked(interactive);
+        }
+    }
 
     public void noteMobileRadioPowerState(int powerState, long timestampNs) {
         enforceCallingPermission();
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/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/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/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1f38eb6..3ae0fd5 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -393,11 +393,7 @@
 
         // Initialize screen state for battery stats.
         try {
-            if (mPowerState.getScreenState() != Display.STATE_OFF) {
-                mBatteryStats.noteScreenOn();
-            } else {
-                mBatteryStats.noteScreenOff();
-            }
+            mBatteryStats.noteScreenState(mPowerState.getScreenState());
             mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
         } catch (RemoteException ex) {
             // same process
@@ -641,11 +637,7 @@
         if (mPowerState.getScreenState() != state) {
             mPowerState.setScreenState(state);
             try {
-                if (state != Display.STATE_OFF) {
-                    mBatteryStats.noteScreenOn();
-                } else {
-                    mBatteryStats.noteScreenOff();
-                }
+                mBatteryStats.noteScreenState(state);
             } catch (RemoteException ex) {
                 // same process
             }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 91afec7..7f43e43 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -21,6 +21,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.SystemProperties;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayEventReceiver;
@@ -47,8 +48,6 @@
             new SparseArray<LocalDisplayDevice>();
     private HotplugDisplayEventReceiver mHotplugReceiver;
 
-    private final SurfaceControl.PhysicalDisplayInfo mTempPhys = new SurfaceControl.PhysicalDisplayInfo();
-
     // Called with SyncRoot lock held.
     public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
             Context context, Handler handler, Listener listener) {
@@ -68,14 +67,31 @@
 
     private void tryConnectDisplayLocked(int builtInDisplayId) {
         IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
-        if (displayToken != null && SurfaceControl.getDisplayInfo(displayToken, mTempPhys)) {
+        if (displayToken != null) {
+            SurfaceControl.PhysicalDisplayInfo[] configs =
+                    SurfaceControl.getDisplayConfigs(displayToken);
+            if (configs == null) {
+                // There are no valid configs for this device, so we can't use it
+                Slog.w(TAG, "No valid configs found for display device " +
+                        builtInDisplayId);
+                return;
+            }
+            int activeConfig = SurfaceControl.getActiveConfig(displayToken);
+            if (activeConfig < 0) {
+                // There is no active config, and for now we don't have the
+                // policy to set one.
+                Slog.w(TAG, "No active config found for display device " +
+                        builtInDisplayId);
+                return;
+            }
             LocalDisplayDevice device = mDevices.get(builtInDisplayId);
             if (device == null) {
                 // Display was added.
-                device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys);
+                device = new LocalDisplayDevice(displayToken, builtInDisplayId,
+                        configs[activeConfig]);
                 mDevices.put(builtInDisplayId, device);
                 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
-            } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) {
+            } else if (device.updatePhysicalDisplayInfoLocked(configs[activeConfig])) {
                 // Display properties changed.
                 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
             }
@@ -228,4 +244,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index a165f26..14ef5a9 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -146,9 +146,7 @@
 
         @Override
         public void performTraversalInTransactionLocked() {
-            if (mSurface != null) {
-                setSurfaceInTransactionLocked(mSurface);
-            }
+            setSurfaceInTransactionLocked(mSurface);
         }
 
         public void setSurfaceLocked(Surface surface) {
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index fd2f8a1..8968da3 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -642,8 +642,9 @@
             try {
                 synchronized (mMcuHal) {
                     if (mReleased) {
-                        throw new IllegalStateException("This operation cannot be performed "
-                                + "because the dream has ended.");
+                        Slog.w(TAG, "Ignoring message to MCU HAL because the dream "
+                                + "has already ended: " + msg);
+                        return null;
                     }
                     return mMcuHal.sendMessage(msg, arg);
                 }
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 c87fc99..b103a4d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -40,7 +40,7 @@
  *
  * <p>Declared as package-private, accessed by {@link HdmiControlService} only.
  */
-class HdmiCecController {
+final class HdmiCecController {
     private static final String TAG = "HdmiCecController";
 
     private static final byte[] EMPTY_BODY = EmptyArray.BYTE;
@@ -313,6 +313,63 @@
         return mDeviceInfos.get(logicalAddress);
     }
 
+    /**
+     * Add a new logical address to the device. Device's HW should be notified
+     * when a new logical address is assigned to a device, so that it can accept
+     * a command having available destinations.
+     *
+     * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     *
+     * @param newLogicalAddress a logical address to be added
+     * @return 0 on success. Otherwise, returns negative value
+     */
+    int addLogicalAddress(int newLogicalAddress) {
+        if (HdmiCec.isValidAddress(newLogicalAddress)) {
+            return nativeAddLogicalAddress(mNativePtr, newLogicalAddress);
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * Clear all logical addresses registered in the device.
+     *
+     * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     */
+    void clearLogicalAddress() {
+        nativeClearLogicalAddress(mNativePtr);
+    }
+
+    /**
+     * Return the physical address of the device.
+     *
+     * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     *
+     * @return CEC physical address of the device. The range of success address
+     *         is between 0x0000 and 0xFFFF. If failed it returns -1
+     */
+    int getPhysicalAddress() {
+        return nativeGetPhysicalAddress(mNativePtr);
+    }
+
+    /**
+     * Return CEC version of the device.
+     *
+     * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     */
+    int getVersion() {
+        return nativeGetVersion(mNativePtr);
+    }
+
+    /**
+     * Return vendor id of the device.
+     *
+     * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     */
+    int getVendorId() {
+        return nativeGetVendorId(mNativePtr);
+    }
+
     private void init(HdmiControlService service, long nativePtr) {
         mIoHandler = new IoHandler(service.getServiceLooper());
         mControlHandler = new ControlHandler(service.getServiceLooper());
@@ -364,6 +421,11 @@
     }
 
     private static native long nativeInit(HdmiCecController handler);
-    private static native int nativeSendCecCommand(long contollerPtr, int srcAddress,
+    private static native int nativeSendCecCommand(long controllerPtr, int srcAddress,
             int dstAddress, byte[] body);
+    private static native int nativeAddLogicalAddress(long controllerPtr, int logicalAddress);
+    private static native void nativeClearLogicalAddress(long controllerPtr);
+    private static native int nativeGetPhysicalAddress(long controllerPtr);
+    private static native int nativeGetVersion(long controllerPtr);
+    private static native int nativeGetVendorId(long controllerPtr);
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 7c1995e..f99c717 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -18,6 +18,8 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.hardware.hdmi.HdmiCecMessage;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.util.Slog;
@@ -77,4 +79,41 @@
     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/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index ab2a723..3dc17fc 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -238,6 +238,8 @@
         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++) {
@@ -249,6 +251,13 @@
         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);
     }
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index ce4c1ed..b41b478 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -21,8 +21,7 @@
 public interface NotificationDelegate {
     void onSetDisabled(int status);
     void onClearAll(int callingUid, int callingPid, int userId);
-    void onNotificationClick(int callingUid, int callingPid,
-            String pkg, String tag, int id, int userId);
+    void onNotificationClick(int callingUid, int callingPid, String key);
     void onNotificationClear(int callingUid, int callingPid,
             String pkg, String tag, int id, int userId);
     void onNotificationError(int callingUid, int callingPid,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 2e52983..7aa5d79 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -602,10 +602,20 @@
         }
 
         @Override
-        public void onNotificationClick(int callingUid, int callingPid,
-                String pkg, String tag, int id, int userId) {
-            cancelNotification(callingUid, callingPid, pkg, tag, id, Notification.FLAG_AUTO_CANCEL,
-                    Notification.FLAG_FOREGROUND_SERVICE, false, userId, REASON_DELEGATE_CLICK, null);
+        public void onNotificationClick(int callingUid, int callingPid, String key) {
+            synchronized (mNotificationList) {
+                EventLogTags.writeNotificationClicked(key);
+                NotificationRecord r = mNotificationsByKey.get(key);
+                if (r == null) {
+                    Log.w(TAG, "No notification with key: " + key);
+                    return;
+                }
+                StatusBarNotification sbn = r.sbn;
+                cancelNotification(callingUid, callingPid, sbn.getPackageName(), sbn.getTag(),
+                        sbn.getId(), Notification.FLAG_AUTO_CANCEL,
+                        Notification.FLAG_FOREGROUND_SERVICE, false, r.getUserId(),
+                        REASON_DELEGATE_CLICK, null);
+            }
         }
 
         @Override
@@ -1612,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,
diff --git a/services/core/java/com/android/server/pm/ForwardingIntentFilter.java b/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
index aba796b..85bde98 100644
--- a/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
+++ b/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
@@ -32,22 +32,29 @@
  */
 class ForwardingIntentFilter extends IntentFilter {
     private static final String ATTR_USER_ID_DEST = "userIdDest";
+    private static final String ATTR_REMOVABLE = "removable";
     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;
+    boolean mRemovable;
 
-    ForwardingIntentFilter(IntentFilter filter, int userIdDest) {
+    ForwardingIntentFilter(IntentFilter filter, boolean removable, int userIdDest) {
         super(filter);
         mUserIdDest = userIdDest;
+        mRemovable = removable;
     }
 
     public int getUserIdDest() {
         return mUserIdDest;
     }
 
+    public boolean isRemovable() {
+        return mRemovable;
+    }
+
     ForwardingIntentFilter(XmlPullParser parser) throws XmlPullParserException, IOException {
         String userIdDestString = parser.getAttributeValue(null, ATTR_USER_ID_DEST);
         if (userIdDestString == null) {
@@ -58,6 +65,10 @@
         } else {
             mUserIdDest = Integer.parseInt(userIdDestString);
         }
+        String removableString = parser.getAttributeValue(null, ATTR_REMOVABLE);
+        if (removableString != null) {
+            mRemovable = Boolean.parseBoolean(removableString);
+        }
         int outerDepth = parser.getDepth();
         String tagName = parser.getName();
         int type;
@@ -89,6 +100,7 @@
 
     public void writeToXml(XmlSerializer serializer) throws IOException {
         serializer.attribute(null, ATTR_USER_ID_DEST, Integer.toString(mUserIdDest));
+        serializer.attribute(null, ATTR_REMOVABLE, Boolean.toString(mRemovable));
         serializer.startTag(null, ATTR_FILTER);
             super.writeToXml(serializer);
         serializer.endTag(null, ATTR_FILTER);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a133d42..6a843a8 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11112,42 +11112,32 @@
         }
     }
 
-    /*
-     * 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");
-        }
+    public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int userIdOrig,
+            int userIdDest) {
+        mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
         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));
+                    new ForwardingIntentFilter(filter, removable, 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");
-        }
+        mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
         synchronized (mPackages) {
             ForwardingIntentResolver fir = mSettings.editForwardingIntentResolverLPw(userIdOrig);
             HashSet<ForwardingIntentFilter> set =
                     new HashSet<ForwardingIntentFilter>(fir.filterSet());
             for (ForwardingIntentFilter fif : set) {
-                fir.removeFilter(fif);
+                if (fif.isRemovable()) fir.removeFilter(fif);
             }
             mSettings.writePackageRestrictionsLPr(userIdOrig);
         }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 14df347..3239b46 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1092,6 +1092,9 @@
             // on next startup, in case the runtime stops now before stopping and
             // removing the user completely.
             user.partial = true;
+            // Mark it as disabled, so that it isn't returned any more when
+            // profiles are queried.
+            user.flags |= UserInfo.FLAG_DISABLED;
             writeUserLocked(user);
         }
         if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
@@ -1120,6 +1123,7 @@
         // wiping the user's system directory and removing from the user list
         long ident = Binder.clearCallingIdentity();
         try {
+            final boolean isManaged = getUserInfo(userHandle).isManagedProfile();
             Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
             addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
             mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
@@ -1140,6 +1144,11 @@
                                             removeUserStateLocked(userHandle);
                                         }
                                     }
+                                    // Send broadcast to notify system that the user removed was a
+                                    // managed user.
+                                    if (isManaged) {
+                                        sendProfileRemovedBroadcast(userHandle);
+                                    }
                                 }
                             }.start();
                         }
@@ -1191,6 +1200,13 @@
         parent.delete();
     }
 
+    private void sendProfileRemovedBroadcast(int userHandle) {
+        Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+        managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(userHandle));
+        // Note: This makes an assumption that the parent owner is user 0.
+        mContext.sendBroadcastAsUser(managedProfileIntent, UserHandle.OWNER, null);
+    }
+
     @Override
     public Bundle getApplicationRestrictions(String packageName) {
         return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index d9e95c7..2d6cc7c 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -132,6 +132,11 @@
         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
         mScreenOffIntent.addFlags(
                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+
+        // Initialize interactive state for battery stats.
+        try {
+            mBatteryStats.noteInteractive(true);
+        } catch (RemoteException ex) { }
     }
 
     /**
@@ -259,7 +264,14 @@
                 // Going to sleep...
                 mLastGoToSleepReason = reason;
             }
-            mInputManagerInternal.setInteractive(interactive);
+        }
+
+        mInputManagerInternal.setInteractive(interactive);
+
+        if (interactive) {
+            try {
+                mBatteryStats.noteInteractive(true);
+            } catch (RemoteException ex) { }
         }
     }
 
@@ -289,6 +301,12 @@
                 }
             }
         }
+
+        if (!interactive) {
+            try {
+                mBatteryStats.noteInteractive(false);
+            } catch (RemoteException ex) { }
+        }
     }
 
     /**
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/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 91f796b..022bdae 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -546,13 +546,13 @@
     }
 
     @Override
-    public void onNotificationClick(String pkg, String tag, int id, int userId) {
+    public void onNotificationClick(String key) {
         enforceStatusBarService();
         final int callingUid = Binder.getCallingUid();
         final int callingPid = Binder.getCallingPid();
         long identity = Binder.clearCallingIdentity();
         try {
-            mNotificationDelegate.onNotificationClick(callingUid, callingPid, pkg, tag, id, userId);
+            mNotificationDelegate.onNotificationClick(callingUid, callingPid, key);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index 527216d..27c8876 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -43,6 +43,16 @@
 
     // Send message to other device. Note that it runs in IO thread.
     int sendMessage(const cec_message_t& message);
+    // Add a logical address to device.
+    int addLogicalAddress(cec_logical_address_t address);
+    // Clear all logical address registered to the device.
+    void clearLogicaladdress();
+    // Get physical address of device.
+    int getPhysicalAddress();
+    // Get CEC version from driver.
+    int getVersion();
+    // Get vendor id used for vendor command.
+    uint32_t getVendorId();
 
 private:
     // Propagate the message up to Java layer.
@@ -94,6 +104,34 @@
     return mDevice->send_message(mDevice, &message);
 }
 
+int HdmiCecController::addLogicalAddress(cec_logical_address_t address) {
+    return mDevice->add_logical_address(mDevice, address);
+}
+
+void HdmiCecController::clearLogicaladdress() {
+    mDevice->clear_logical_address(mDevice);
+}
+
+int HdmiCecController::getPhysicalAddress() {
+    uint16_t physicalAddress = 0xFFFF;
+    if (mDevice->get_physical_address(mDevice, &physicalAddress) == 0) {
+        return physicalAddress;
+    }
+    return -1;
+}
+
+int HdmiCecController::getVersion() {
+    int version = 0;
+    mDevice->get_version(mDevice, &version);
+    return version;
+}
+
+uint32_t HdmiCecController::getVendorId() {
+    uint32_t vendorId = 0;
+    mDevice->get_vendor_id(mDevice, &vendorId);
+    return vendorId;
+}
+
 // static
 void HdmiCecController::checkAndClearExceptionFromCallback(JNIEnv* env,
         const char* methodName) {
@@ -180,12 +218,51 @@
     return controller->sendMessage(message);
 }
 
+static jint nativeAddLogicalAddress(JNIEnv* env, jclass clazz,
+        jlong controllerPtr, jint logicalAddress) {
+    HdmiCecController* controller =
+            reinterpret_cast<HdmiCecController*>(controllerPtr);
+    return controller->addLogicalAddress(
+            static_cast<cec_logical_address_t>(logicalAddress));
+}
+
+static void nativeClearLogicalAddress(JNIEnv* env, jclass clazz,
+        jlong controllerPtr) {
+    HdmiCecController* controller =
+            reinterpret_cast<HdmiCecController*>(controllerPtr);
+    controller->clearLogicaladdress();
+}
+
+static jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz,
+        jlong controllerPtr) {
+    HdmiCecController* controller =
+            reinterpret_cast<HdmiCecController*>(controllerPtr);
+    return controller->getPhysicalAddress();
+}
+
+static jint nativeGetVersion(JNIEnv* env, jclass clazz,
+        jlong controllerPtr) {
+    HdmiCecController* controller =
+            reinterpret_cast<HdmiCecController*>(controllerPtr);
+    return controller->getVersion();
+}
+
+static jint nativeGetVendorId(JNIEnv* env, jclass clazz, jlong controllerPtr) {
+    HdmiCecController* controller =
+            reinterpret_cast<HdmiCecController*>(controllerPtr);
+    return controller->getVendorId();
+}
+
 static JNINativeMethod sMethods[] = {
     /* name, signature, funcPtr */
     { "nativeInit", "(Lcom/android/server/hdmi/HdmiCecController;)J",
             (void *) nativeInit },
-    { "nativeSendCecCommand", "(JII[B)I",
-            (void *) nativeSendCecCommand },
+    { "nativeSendCecCommand", "(JII[B)I", (void *) nativeSendCecCommand },
+    { "nativeAddLogicalAddress", "(JI)I", (void *) nativeAddLogicalAddress },
+    { "nativeClearLogicalAddress", "(J)V", (void *) nativeClearLogicalAddress },
+    { "nativeGetPhysicalAddress", "(J)I", (void *) nativeGetPhysicalAddress },
+    { "nativeGetVersion", "(J)I", (void *) nativeGetVersion },
+    { "nativeGetVendorId", "(J)I", (void *) nativeGetVendorId },
 };
 
 #define CLASS_PATH "com/android/server/hdmi/HdmiCecController"
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index aaa97eb..7a0d1c7 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);
@@ -3081,7 +3082,7 @@
         }
     }
 
-    public void forwardMatchingIntents(ComponentName who, IntentFilter filter, int flags) {
+    public void addForwardingIntentFilter(ComponentName who, IntentFilter filter, int flags) {
         int callingUserId = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
@@ -3093,10 +3094,12 @@
             long id = Binder.clearCallingIdentity();
             try {
                 if ((flags & DevicePolicyManager.FLAG_TO_PRIMARY_USER) != 0) {
-                    pm.addForwardingIntentFilter(filter, callingUserId, UserHandle.USER_OWNER);
+                    pm.addForwardingIntentFilter(filter, true /*removable*/, callingUserId,
+                            UserHandle.USER_OWNER);
                 }
                 if ((flags & DevicePolicyManager.FLAG_TO_MANAGED_PROFILE) != 0) {
-                    pm.addForwardingIntentFilter(filter, UserHandle.USER_OWNER, callingUserId);
+                    pm.addForwardingIntentFilter(filter, true /*removable*/, UserHandle.USER_OWNER,
+                            callingUserId);
                 }
             } catch (RemoteException re) {
                 // Shouldn't happen
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/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 992ef4b..a016933 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -701,4 +701,21 @@
             VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int userIdOrig,
+            int userIdDest) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void clearForwardingIntentFilters(int userIdOrig) {
+        throw new UnsupportedOperationException();
+    }
 }
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..5c273de1
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -0,0 +1,146 @@
+/*
+ * 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.webkit.WebChromeClient;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+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));
+        // For testing with a functor in the tree
+//        WebView wv = new WebView(this);
+//        wv.setWebViewClient(new WebViewClient());
+//        wv.setWebChromeClient(new WebChromeClient());
+//        wv.loadUrl("http://theverge.com");
+//        layout.addView(wv, new LayoutParams(LayoutParams.MATCH_PARENT, 100));
+
+        layout.addView(new CircleView(this),
+                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+        setContentView(layout);
+    }
+
+    static class CircleView extends View {
+        static final int DURATION = 500;
+
+        private boolean mToggle = false;
+        ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<RenderNodeAnimator>();
+
+        CanvasProperty<Float> mX;
+        CanvasProperty<Float> mY;
+        CanvasProperty<Float> mRadius;
+        CanvasProperty<Paint> mPaint;
+
+        CircleView(Context c) {
+            super(c);
+            setClickable(true);
+
+            mX = CanvasProperty.createFloat(200.0f);
+            mY = CanvasProperty.createFloat(200.0f);
+            mRadius = CanvasProperty.createFloat(150.0f);
+
+            Paint p = new Paint();
+            p.setAntiAlias(true);
+            p.setColor(0xFFFF0000);
+            p.setStyle(Style.STROKE);
+            p.setStrokeWidth(60.0f);
+            mPaint = CanvasProperty.createPaint(p);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+
+            if (canvas.isHardwareAccelerated()) {
+                HardwareCanvas hwcanvas = (HardwareCanvas) canvas;
+                hwcanvas.drawCircle(mX, mY, mRadius, mPaint);
+            }
+        }
+
+        @Override
+        public boolean performClick() {
+            for (int i = 0; i < mRunningAnimations.size(); i++) {
+                mRunningAnimations.get(i).cancel();
+            }
+            mRunningAnimations.clear();
+
+            mToggle = !mToggle;
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mX, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 400.0f : 200.0f));
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mY, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 600.0f : 200.0f));
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mRadius, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 250.0f : 150.0f));
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mPaint, RenderNodeAnimator.PAINT_ALPHA,
+                    RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 64.0f : 255.0f));
+
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mPaint, RenderNodeAnimator.PAINT_STROKE_WIDTH,
+                    RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 5.0f : 60.0f));
+
+            for (int i = 0; i < mRunningAnimations.size(); i++) {
+                mRunningAnimations.get(i).start(this);
+            }
+
+            if (mToggle) {
+                post(new Runnable() {
+                    @Override
+                    public void run() {
+                        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "pretendBusy");
+                        try {
+                            Thread.sleep(DURATION);
+                        } catch (InterruptedException e) {
+                        }
+                        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+                    }
+                });
+            }
+
+            return true;
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
index 8c02539..a3f4ddc 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
@@ -57,7 +57,7 @@
             
             mPaint = new Paint();
             mPaint.setAntiAlias(true);
-            mPaint.setColor(0xffffffff);
+            mPaint.setColor(0xff00ffff);
         }
 
         @Override
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index 1d209dd..8f9cf58 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -19,8 +19,6 @@
 
 public class MainActivity extends Activity implements OnItemClickListener {
 
-    static final int TRANSLATION_Y = 1;
-    static final int DELTA_TYPE_DELTA = 1;
     static final int DURATION = 400;
 
     static final String KEY_NAME = "name";
@@ -75,7 +73,7 @@
             float delta = (pos - clickedPosition) * 1.1f;
             if (delta == 0) delta = -1;
             RenderNodeAnimator animator = new RenderNodeAnimator(
-                    TRANSLATION_Y, DELTA_TYPE_DELTA, dy * delta);
+                    RenderNodeAnimator.TRANSLATION_Y, RenderNodeAnimator.DELTA_TYPE_DELTA, dy * delta);
             animator.setDuration(DURATION);
             animator.start(child);
         }
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
index 88ae398..7ba01b1 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
@@ -22,7 +22,7 @@
 import android.widget.GridLayout;
 
 @SuppressWarnings({"UnusedDeclaration"})
-public class VectorDrawable01 extends Activity implements View.OnClickListener {
+public class VectorDrawable01 extends Activity {
     private static final String LOGCAT = "VectorDrawable1";
     int[] icon = {
             R.drawable.vector_drawable01,
@@ -61,28 +61,10 @@
             button.setWidth(200);
             button.setBackgroundResource(icon[i]);
             container.addView(button);
-            button.setOnClickListener(this);
         }
-        Button b = new Button(this);
-        b.setText("Run All");
-        b.setOnClickListener(new View.OnClickListener(){
 
-            @Override
-            public void onClick(View v) {
-                for (int i = 0; i < bArray.length; i++) {
-                    VectorDrawable d = (VectorDrawable)  bArray[i].getBackground();
-                    d.start();
-                }
-            }});
-        container.addView(b);
         setContentView(container);
 
     }
 
-    @Override
-    public void onClick(View v) {
-        VectorDrawable d = (VectorDrawable) v.getBackground();
-        d.start();
-    }
-
 }
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index 3929298..b918cdd 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -25,7 +25,7 @@
 import java.text.DecimalFormat;
 
 @SuppressWarnings({"UnusedDeclaration"})
-public class VectorDrawablePerformance extends Activity implements View.OnClickListener {
+public class VectorDrawablePerformance extends Activity {
     private static final String LOGCAT = "VectorDrawable1";
     protected int[] icon = {
             R.drawable.vector_drawable01,
@@ -76,7 +76,6 @@
             button.setWidth(200);
             button.setBackgroundResource(icon[i]);
             container.addView(button);
-            button.setOnClickListener(this);
         }
         setContentView(scrollView);
         time =  android.os.SystemClock.elapsedRealtimeNanos()-time;
@@ -85,10 +84,4 @@
         t.setBackgroundColor(0xFF000000);
         container.addView(t);
     }
-
-    @Override
-    public void onClick(View v) {
-        VectorDrawable d = (VectorDrawable) v.getBackground();
-        d.start();
-    }
 }
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/Resource.cpp b/tools/aapt/Resource.cpp
index d0581f6..1348be3 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -1261,12 +1261,13 @@
         while ((err=it.next()) == NO_ERROR) {
             String8 src = it.getFile()->getPrintableSource();
             err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
-            if (err != NO_ERROR) {
+            if (err == NO_ERROR) {
+                ResXMLTree block;
+                block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true);
+                checkForIds(src, block);
+            } else {
                 hasErrors = true;
             }
-            ResXMLTree block;
-            block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true);
-            checkForIds(src, block);
         }
 
         if (err < NO_ERROR) {
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index b445b8a..6eab65b 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -865,6 +865,21 @@
         pseudoBidiParams.country[0] = 'X';
         pseudoBidiParams.country[1] = 'B';
 
+    // We should skip resources for pseudolocales if they were
+    // already added automatically. This is a fix for a transition period when
+    // manually pseudolocalized resources may be expected.
+    // TODO: remove this check after next SDK version release.
+    if ((bundle->getPseudolocalize() & PSEUDO_ACCENTED &&
+         curParams.locale == pseudoParams.locale) ||
+        (bundle->getPseudolocalize() & PSEUDO_BIDI &&
+         curParams.locale == pseudoBidiParams.locale)) {
+        SourcePos(in->getPrintableSource(), 0).warning(
+                "Resource file %s is skipped as pseudolocalization"
+                " was done automatically.",
+                in->getPrintableSource().string());
+        return NO_ERROR;
+    }
+
     while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
         if (code == ResXMLTree::START_TAG) {
             const String16* curTag = NULL;